├── .bowerrc
├── .gitignore
├── README.md
├── bower.json
├── gortfolio
├── controllers
│ ├── ctrl.main.go
│ └── ctrl.user.go
├── middlewares
│ ├── gzip.go
│ └── middleware.go
├── models
│ ├── model.media.go
│ ├── model.portfolio.go
│ ├── model.project.go
│ ├── model.sys.go
│ └── model.user.go
├── router.go
├── serve.go
├── utils
│ └── dateTime.go
└── views
│ └── index.html
├── gulpfile.js
├── package.json
├── public
├── app
│ ├── actions
│ │ ├── navActions.js
│ │ ├── portfolioActions.js
│ │ ├── projectsActions.js
│ │ └── routeCoverActions.js
│ ├── app.js
│ ├── components
│ │ ├── Grid.js
│ │ ├── Navtoggle.js
│ │ ├── RouteCover.js
│ │ └── Typer.js
│ ├── constants
│ │ ├── commonConst.js
│ │ ├── portfolioConst.js
│ │ └── projectsConst.js
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── index.js
│ ├── pages
│ │ ├── About.js
│ │ ├── Contact.js
│ │ ├── Ideas.js
│ │ ├── Intro.js
│ │ ├── Portfolio.js
│ │ ├── PortfolioItem.js
│ │ ├── Project.js
│ │ └── Projects.js
│ ├── routes.js
│ ├── service
│ │ ├── gridSvc.js
│ │ └── gridSvc6.js
│ └── stores
│ │ ├── navStore.js
│ │ ├── projectsStore.js
│ │ └── routeCoverStore.js
├── data
│ ├── portfolio.json
│ ├── portfolio
│ │ └── item1.html
│ ├── projects.json
│ └── projects
│ │ ├── project1.html
│ │ ├── project2.html
│ │ └── project3.html
├── images
│ ├── u1.jpg
│ ├── u10.jpg
│ ├── u11.jpg
│ ├── u12.jpg
│ ├── u13.jpg
│ ├── u2.jpg
│ ├── u3.jpg
│ ├── u4.jpg
│ ├── u5.jpg
│ ├── u6.jpg
│ ├── u7.jpg
│ ├── u8.jpg
│ └── u9.jpg
├── img
│ ├── cover
│ │ ├── contact.jpg
│ │ ├── forest.jpg
│ │ ├── forest2_dim.jpg
│ │ ├── intro.jpg
│ │ ├── portrait.jpg
│ │ ├── woods.jpg
│ │ └── woods_dim.jpg
│ ├── d5logo.svg
│ ├── favicon.png
│ ├── icons
│ │ ├── arrow-down.svg
│ │ ├── arrow-left.svg
│ │ ├── arrow-right.svg
│ │ ├── ios7-close-empty.svg
│ │ ├── ios7-close-outline-light.svg
│ │ ├── ios7-close-outline.svg
│ │ ├── next.svg
│ │ └── prev.svg
│ ├── page
│ │ ├── drag.svg
│ │ ├── keys.svg
│ │ ├── switchmax.svg
│ │ └── switchmin.svg
│ ├── pattern.png
│ └── social
│ │ ├── Sina_Weibo-512.png
│ │ ├── be.png
│ │ ├── facebook-icon.png
│ │ ├── git.jpg
│ │ ├── github.png
│ │ ├── sc.png
│ │ └── zhihu.png
├── index.html
├── lib
│ └── modernizr.js
├── scss
│ ├── _color_palette.scss
│ ├── _mixins.scss
│ ├── _var.scss
│ ├── animation.scss
│ ├── buttons.scss
│ ├── common_style.scss
│ ├── component
│ │ ├── about.scss
│ │ ├── blog.scss
│ │ ├── contact.scss
│ │ ├── form.scss
│ │ ├── grid.scss
│ │ ├── ideas.scss
│ │ ├── intro.scss
│ │ ├── portfolio.scss
│ │ ├── project.scss
│ │ └── projects.scss
│ ├── layout.scss
│ ├── main.scss
│ ├── plugins.scss
│ └── reset.scss
└── video
│ ├── splash.mp4
│ └── splash.webm
├── server.go
├── server
├── config
│ ├── config.go
│ ├── config_test.go
│ └── db.go
├── controllers
│ ├── ctrl.sys.go
│ └── ctrl.user.go
├── main.go
├── models
│ ├── model.media.go
│ ├── model.portfolio.go
│ ├── model.project.go
│ ├── model.sys.go
│ └── model.user.go
├── routes
│ └── routes.go
├── utils
│ └── dateTime.go
└── views
│ ├── index.html
│ └── install.html
├── snapshot.png
└── test.go
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/vendor"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.seed
2 | *.log
3 | *.csv
4 | *.dat
5 | *.out
6 | *.pid
7 | *.gz
8 |
9 | npm-debug.log
10 | node_modules
11 | .DS_Store
12 | .nodemonignore
13 | .sass-cache/
14 | .bower-*/
15 | .idea/
16 |
17 | app_config.json
18 |
19 | public/vendor/
20 | public/build/
21 | public/css/*.css
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Gortfolio
2 | ==========
3 | ___ _ _
4 | _ / __) | |(_)
5 | ____ ___ ____ _| |_ _| |__ ___ | | _ ___
6 | / _ |/ _ \ / ___|_ _|_ __) _ \| || |/ _ \
7 | ( (_| | |_| | | | |_ | | | |_| | || | |_| |
8 | \___ |\___/|_| \__) |_| \___/ \_)_|\___/
9 | (_____|
10 |
11 | ================================================
12 |
13 |
14 |
15 | ##under development.......
16 | DEMO:[http://glexe.com](http://eisneim.github.io/gortfolio/)
17 |
18 | 
19 |
20 | the goal is to create an awesome & easy to use portfolio site for Designer / Artist / Developer
21 | using:
22 | - Golang as backend language
23 | - React + Flux + react-router + browserify as front end architecture
24 | - Mongodb as database
25 | - Gulp as build tool
26 |
27 | ##TODO
28 | - theme system: seperate frontend and backend and make switch to another front end easily;
29 | - portfolio management:upload, edit, deldate
30 | - improve or ReWrite some slow page or component
31 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gortforlio",
3 | "private": true,
4 | "version": "0.0.1",
5 | "dependencies": {
6 | "snap.svg": "~0.3.0"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/gortfolio/controllers/ctrl.main.go:
--------------------------------------------------------------------------------
1 | package gortfolio
2 |
3 | import (
4 | // "encoding/json"
5 | // "fmt"
6 | "github.com/unrolled/render"
7 | // "gopkg.in/mgo.v2/bson"
8 | // "github.com/julienschmidt/httprouter"
9 | // "log"
10 | // "net/http"
11 | )
12 |
13 | /**
14 | r := render.New(render.Options{
15 | Directory: "templates", // Specify what path to load the templates from.
16 | Layout: "layout", // Specify a layout template. Layouts can call {{ yield }} to render the current template.
17 | Extensions: []string{".tmpl", ".html"}, // Specify extensions to load for templates.
18 | Funcs: []template.FuncMap{AppHelpers}, // Specify helper function maps for templates to access.
19 | Delims: render.Delims{"{[{", "}]}"}, // Sets delimiters to the specified strings.
20 | Charset: "UTF-8", // Sets encoding for json and html content-types. Default is "UTF-8".
21 | IndentJSON: true, // Output human readable JSON.
22 | IndentXML: true, // Output human readable XML.
23 | PrefixJSON: []byte(")]}',\n"), // Prefixes JSON responses with the given bytes.
24 | PrefixXML: []byte(""), // Prefixes XML responses with the given bytes.
25 | HTMLContentType: "application/xhtml+xml", // Output XHTML content type instead of default "text/html".
26 | IsDevelopment: true, // Render will now recompile the templates on every HTML response.
27 | })
28 | */
29 | var (
30 | R = render.New(render.Options{
31 | IndentJSON: false,
32 | Directory: "../views",
33 | IsDevelopment: true,
34 | })
35 | ColUser *mgo.Collection
36 | DB *mgo.Database
37 | )
38 |
39 | // func HandleFunc( router httprouter.Router ) {
40 | // return func( w http.ResponseWriter, r *http.Request, _ httprouter.Params ){
41 |
42 | // }
43 | // }
44 |
--------------------------------------------------------------------------------
/gortfolio/controllers/ctrl.user.go:
--------------------------------------------------------------------------------
1 | package gortfolio
2 |
3 | import (
4 | // "fmt"
5 | "github.com/julienschmidt/httprouter"
6 | "gopkg.in/mgo.v2/bson"
7 | "log"
8 | "net/http"
9 | "time"
10 | )
11 |
12 | func UserLogin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
13 | type Person struct {
14 | Id bson.ObjectId `bson:"_id,omitempty" json:"-"`
15 | FirstName string `bson:"firstName" json:"firstName"`
16 | MiddleName string `bson:"middleName,omitempty" json:"middleName,omitempty"`
17 | LastName string `bson:"lastName" json:"lastName"`
18 | Inserted time.Time `bson:"inserted" json:"-"`
19 | }
20 |
21 | // err = ColUser.Insert(&Person{"Ale", "+55 53 8116 9639"},
22 | // &Person{"Cla", "+55 53 8402 8510"})
23 | // if err != nil {
24 | // log.Fatal(err)
25 | // }
26 |
27 | result := Person{}
28 | // err = ColUser.Find(bson.M{"phone": "13472783207"}).One(&result)
29 | // if err != nil {
30 | // log.Fatal(err)
31 | // }
32 |
33 | R.JSON(w, http.StatusOK, result)
34 | }
35 |
36 | func Test(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
37 |
38 | type book struct {
39 | Title string `json:"title"`
40 | Author string `json:"author"`
41 | Id int `json:"id"`
42 | }
43 | var books = make([]book, 0)
44 |
45 | books = append(books, book{"Ender's Game", "Orson Scott Card", 1})
46 | books = append(books, book{"Code Complete", "Steve McConnell", 2})
47 | books = append(books, book{"World War Z", "Max Brooks", 3})
48 |
49 | // w.Write(books)
50 | // fmt.Fprint(w, books)
51 | R.JSON(w, http.StatusOK, books)
52 | }
53 |
54 | func NewUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
55 |
56 | type User struct {
57 | Id_ bson.ObjectId `bson:"_id"`
58 | Username string `bson:"username"`
59 | // Salt string `bson:"salt"`
60 | // Hash string `bson:"hash"`
61 | // Email string `bson:"email"`
62 | // Avatar string `bson:"avatar"`
63 | }
64 | err := ColUser.Insert(&User{bson.NewObjectId(), "Ale"},
65 | &User{bson.NewObjectId(), "Eisneim"})
66 | if err != nil {
67 | log.Fatal(err)
68 | }
69 |
70 | var users []User
71 |
72 | ColUser.Find(nil).All(&users)
73 |
74 | R.JSON(w, http.StatusOK, users)
75 | }
76 |
--------------------------------------------------------------------------------
/gortfolio/middlewares/gzip.go:
--------------------------------------------------------------------------------
1 | package middlewares
2 |
3 | import (
4 | "compress/gzip"
5 | "net/http"
6 | "strings"
7 | )
8 |
9 | /**
10 | * this one is just for "return" type
11 | * interface just make it possible to switch type onec two type have same "method"s
12 | *
13 | */
14 | type CloseableResponseWriter interface {
15 | http.ResponseWriter
16 | Close()
17 | }
18 |
19 | // ----------------------------------------
20 | type gzipResponseWriter struct {
21 | http.ResponseWriter
22 | *gzip.Writer
23 | }
24 |
25 | func (this gzipResponseWriter) Write(data []byte) (int, error) {
26 | return this.Writer.Write(data)
27 | }
28 |
29 | func (this gzipResponseWriter) Close() {
30 | this.Writer.Close()
31 | }
32 |
33 | func (this gzipResponseWriter) Header() http.Header {
34 | return this.ResponseWriter.Header()
35 | }
36 |
37 | // ----------------------------------------
38 | type closeableResponseWriter struct {
39 | http.ResponseWriter
40 | }
41 |
42 | func (this closeableResponseWriter) Close() {
43 |
44 | }
45 |
46 | func GetResponseWriter(w http.ResponseWriter, req *http.Request) CloseableResponseWriter {
47 | if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
48 | w.Header().Set("Content-Encoding", "gzip")
49 |
50 | gRW := gzipResponseWriter{
51 | ResponseWriter: w,
52 | Writer: gzip.NewWriter(w),
53 | }
54 |
55 | return gRW
56 | } else {
57 | return closeableResponseWriter{ResponseWriter: w}
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/gortfolio/middlewares/middleware.go:
--------------------------------------------------------------------------------
1 | package gortfolio
2 |
3 | import (
4 | "encoding/json"
5 | // "fmt"
6 | "log"
7 | "net/http"
8 | "net/http/httptest"
9 | )
10 |
11 | func JSON_md(h http.Handler) http.Handler {
12 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
13 |
14 | rec := httptest.NewRecorder()
15 | // passing a ResponseRecorder instead of the original RW
16 | h.ServeHTTP(rec, r)
17 | // after this finishes, we have the response recorded
18 | // and can modify it before copying it to the original RW
19 |
20 | // we copy the original headers first
21 | for k, v := range rec.Header() {
22 | w.Header()[k] = v
23 | }
24 |
25 | if rec.Body == nil {
26 | log.Printf("ERROR: response from method is nil\n")
27 | http.Error(w, "Internal server error. check the logs.", http.StatusInternalServerError)
28 | return
29 | }
30 |
31 | // turn respoonse into json
32 | bytes, e := json.Marshal(rec.Body.String())
33 | if e != nil {
34 | http.Error(w, "Error harshalling JSON", http.StatusInternalServerError)
35 | return
36 | }
37 |
38 | // send response and log it
39 | w.Header().Set("Content-Type", "application/json")
40 |
41 | // finally, write out our data
42 | w.Write(bytes)
43 | // then write out the original body
44 | // w.Write( rec.Body.Bytes() )
45 |
46 | log.Printf("%s %s %s %d", r.RemoteAddr, r.Method, r.URL, 200)
47 | })
48 | }
49 |
50 | // ---------------------------------------------------------
51 |
--------------------------------------------------------------------------------
/gortfolio/models/model.media.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Media struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Type string `bson:"type"` // image, audio, video
14 | Src string `bson:"src"`
15 | Name string `bson:"name"`
16 | Size string `bson:"size"`
17 | Author bson.ObjectId `bson:"author"`
18 | ProjectIDs []bson.ObjectId `bson:"projectIDs"`
19 | PortfolioIDs []bson.ObjectId `bson:"portfolioIDs"`
20 | }
21 |
22 | func init() {
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/gortfolio/models/model.portfolio.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Portfolio struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | PortfolioType string `bson:"type"` // video, iilustration, design, paint,
14 | Medias []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Description string `bson:"Description"`
17 | Viewed int `bson:"viewed"`
18 | Voted int `bson:"voted"`
19 | Cards []PortfolioCard `bson:"cards"`
20 | }
21 |
22 | type PortfolioCard struct {
23 | Media bson.ObjectId `bson:"media"`
24 | Type string `bson:"type"` // image, audio, video
25 | Src string `bson:"src"`
26 | Description string `bson:"description"`
27 | }
28 |
29 | func init() {
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/gortfolio/models/model.project.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Project struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Author bson.ObjectId `bson:"author"`
14 | MediaIDs []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Cover bson.ObjectId `bson:"cover"`
17 | Description string `bson:"description"`
18 | ViewCount int `bson:"viewed"`
19 | VoteCount int `bson:"voted"`
20 | Cards []projectCard `bson:"cards"`
21 | Detail string `bson:"detail"`
22 | }
23 |
24 | type projectCard struct {
25 | Media bson.ObjectId `bson:"media"`
26 | Type string `bson:"type"` // image, audio, video
27 | Src string `bson:"src"`
28 | Description string `bson:"description"`
29 | }
30 |
31 | func init() {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/gortfolio/models/model.sys.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Sys struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Author bson.ObjectId `bson:"author"`
14 | Medias []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Description string `bson:"Description"`
17 | Viewed int `bson:"viewed"`
18 | Voted int `bson:"voted"`
19 | Cards []SysCard `bson:"cards"`
20 | }
21 |
22 | type SysCard struct {
23 | Media bson.ObjectId `bson:"media"`
24 | Type string `bson:"type"` // image, audio, video
25 | Src string `bson:"src"`
26 | Description string `bson:"description"`
27 | }
28 |
29 | func init() {
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/gortfolio/models/model.user.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type User struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Username string `bson:"username"`
14 | Email string `bson:"email"`
15 | Avatar string `bson:"avatar"`
16 | Security userSecurity `bson:"security"`
17 | Posts []bson.ObjectId `bson:"posts"`
18 | }
19 | type userSecurity struct {
20 | Salt string `bson:"salt"`
21 | Hash string `bson:"hash"`
22 | }
23 |
24 | // type userPosts [ bson.ObjectId ]
25 |
26 | func init() {
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/gortfolio/router.go:
--------------------------------------------------------------------------------
1 | package gortfolio
2 |
3 | import (
4 | "github.com/eisneim/gortfolio/gortfolio/controllers"
5 | "github.com/julienschmidt/httprouter"
6 | "net/http"
7 | )
8 |
9 | func RegisterRoutes() {
10 |
11 | // ----------- user apis -----------
12 | Router.GET("/v1/login", UserLogin)
13 |
14 | Router.GET("/test", Test)
15 |
16 | Router.GET("/middleware", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
17 | w.Header().Set("X-We-Modified-This", "Yup")
18 |
19 | w.Write([]byte("这个是前置middleware _______"))
20 | handler(w, r, p)
21 | })
22 |
23 | Router.GET("/insert", NewUser)
24 | // ----------- portfolio api -------
25 |
26 | }
27 |
28 | func handler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
29 | w.Write([]byte(" 这个是个handler "))
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/gortfolio/serve.go:
--------------------------------------------------------------------------------
1 | package gortfolio
2 |
3 | import (
4 | "fmt"
5 | // "io/ioutil"
6 | "github.com/justinas/alice"
7 | "html/template"
8 | "log"
9 | "net/http"
10 | // "strconv"
11 | // "gopkg.in/mgo.v2"
12 | // "gopkg.in/mgo.v2/bson"
13 |
14 | // router
15 | "github.com/julienschmidt/httprouter"
16 | // "github.com/eisneim/gortfolio/gortfolio/controllers"
17 | )
18 |
19 | var (
20 | templates *template.Template
21 | Router = httprouter.New()
22 | )
23 |
24 | func init() {
25 | // teplate cache
26 | templates = template.Must(
27 | template.ParseFiles("./gortfolio/views/index.html"),
28 | )
29 | }
30 |
31 | /*
32 | ------- for testing, useless ------
33 | */
34 | func LoggingMiddleware(h http.Handler) http.Handler {
35 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
36 | log.Println("request started")
37 | w.Write([]byte("md___"))
38 | // h(w, r)
39 | // log.Println("request finished")
40 | h.ServeHTTP(w, r)
41 | // append some thing here;
42 | w.Write([]byte("___md"))
43 | log.Println("request finished")
44 | })
45 | }
46 |
47 | func Serve(port int, dir string) {
48 | // Router.Handle("/", http.RedirectHandler("/static/", 302))
49 | // Router.GET("/", renderIndex)
50 |
51 | // static files
52 | Router.NotFound = http.FileServer(http.Dir(dir)).ServeHTTP
53 |
54 | log.Printf("Running on port %d\n", port)
55 |
56 | middlewareChain := alice.New().Then(Router)
57 |
58 | err := http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", port), middlewareChain)
59 | fmt.Println(err.Error())
60 | }
61 |
62 | func renderIndex(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
63 | templates.ExecuteTemplate(w, "index.html", nil)
64 | // fmt.Fprint(w, "Welcome!\n")
65 | }
66 |
67 | /**
68 | * -------------------------- main middleware-------------
69 | * 1. mongodb connection
70 | * 2. logging
71 | * 3. error handling
72 | */
73 | // type Ghandler struct {
74 | // ResponseWriter http.ResponseWriter
75 | // Request *http.Request
76 | // StartTime time.Time
77 | // Session *mgo.Session
78 | // DB *mgo.Database
79 | // }
80 |
81 | // func NewHandler(w http.ResponseWriter, r *http.Request) Ghandler {
82 | // session, err := mgo.Dial(Config.DB)
83 | // if err != nil {
84 | // panic(err)
85 | // }
86 |
87 | // session.SetMode(mgo.Monotonic, true)
88 |
89 | // return Ghandler{
90 | // ResponseWriter: w,
91 | // Request: r,
92 | // StartTime: time.Now(),
93 | // Session: session,
94 | // DB: session.DB("gopher"),
95 | // }
96 | // }
97 |
98 | // func handlerFun(route Route) http.HandlerFunc {
99 | // return func(w http.ResponseWriter, r *http.Request) {
100 | // /*
101 | // defer func() {
102 | // if e := recover(); e != nil {
103 | // fmt.Println("panic:", e)
104 | // }
105 | // }()*/
106 | // handler := NewHandler(w, r)
107 | // defer handler.Session.Close()
108 |
109 | // url := r.Method + " " + r.URL.Path
110 | // if r.URL.RawQuery != "" {
111 | // url += "?" + r.URL.RawQuery
112 | // }
113 | // fmt.Println(time.Now().Format("2006-01-02 15:04:05"), url)
114 | // if route.Permission == Everyone {
115 | // route.HandlerFunc(handler)
116 | // } else if route.Permission == Authenticated {
117 | // _, ok := currentUser(handler)
118 |
119 | // if !ok {
120 | // http.Redirect(w, r, "/signin", http.StatusFound)
121 | // return
122 | // }
123 |
124 | // route.HandlerFunc(handler)
125 | // } else if route.Permission == Administrator {
126 | // user, ok := currentUser(handler)
127 |
128 | // if !ok {
129 | // http.Redirect(w, r, "/signin", http.StatusFound)
130 | // return
131 | // }
132 |
133 | // if !user.IsSuperuser {
134 | // message(handler, "没有权限", "对不起,你没有权限进行该操作", "error")
135 | // return
136 | // }
137 |
138 | // route.HandlerFunc(handler)
139 | // }
140 | // }
141 | // }
142 |
--------------------------------------------------------------------------------
/gortfolio/utils/dateTime.go:
--------------------------------------------------------------------------------
1 | /**
2 | * date and time parsing utils
3 | */
4 | package utils
5 |
6 | import ()
7 |
8 | func parseTime() {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/gortfolio/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | gort forliot template
11 |
12 |
13 |
14 |
ssssss
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | open = require('gulp-open'),
3 | browserify = require('gulp-browserify'),
4 | concat = require('gulp-concat'),
5 | uglify = require('gulp-uglify'),
6 | livereload = require('gulp-livereload');
7 |
8 | // es6 related things
9 | // var babel = require('gulp-babel');
10 |
11 | // for sass compile and live reload:
12 | var sass = require('gulp-sass'),
13 | autoprefix = require('gulp-autoprefixer'),
14 | minifyCSS = require('gulp-minify-css');
15 |
16 | var paths = {
17 | html: 'public/index.html',
18 | img: 'public/img/**/*',
19 | scss: 'public/scss/**/*.scss',
20 | js: 'public/app/**/*.js',
21 | }
22 | // ---------------------------------------
23 | gulp.task('scss', function() {
24 | // console.log('-----build main.scss');
25 | gulp.src('./public/scss/main.scss' )
26 | .pipe(sass())
27 | .pipe(autoprefix('last 2 versions'))
28 | .pipe(minifyCSS())
29 | .pipe(gulp.dest('./public/css'))
30 | });
31 |
32 |
33 | // ---------------------------------------
34 | gulp.task('browserify',function(){
35 | gulp.src('./public/app/index.js')
36 | // .pipe( babel({
37 | // // optional: ["runtime"],
38 | // }) )
39 | .pipe(browserify({
40 | transform: ['babelify'], // 'babelify' reactify
41 | insertGlobals : true,
42 | }))
43 | .on( "error", handleError)
44 | .pipe(gulp.dest('./public/build/'))
45 | })
46 |
47 | gulp.task('build-js',function(){
48 | gulp.src('./public/app/index.js')
49 | .pipe(browserify({
50 | transform: ['babelify'],
51 | insertGlobals : true,
52 | debug : false,
53 | }))
54 | .pipe(uglify({
55 | compress:false,
56 | mangle:true,
57 | }))
58 | .pipe(gulp.dest('./public/build/'));
59 | })
60 |
61 | //launch browser in a port
62 | gulp.task('open',function(){
63 | var options = {
64 | url:'http://localhost:'+ port,
65 | }
66 | gulp.src('./public/index.html')
67 | .pipe(open('',options));
68 | })
69 |
70 | // watch files for live reload
71 | gulp.task('watch',function(){
72 | livereload.listen();
73 | gulp.watch('./public/build/**/*.js').on('change', livereload.changed);
74 | gulp.watch( paths.html ).on('change', livereload.changed);
75 | gulp.watch('./public/css/**/*.css').on('change', livereload.changed);
76 |
77 | gulp.watch( paths.js ,['browserify']);
78 | gulp.watch( paths.scss ,['scss']);
79 | });
80 |
81 | gulp.task('default',['browserify']);
82 |
83 | gulp.task('build',['build-js','scss']);
84 |
85 | gulp.task('serve',['browserify','watch']);
86 |
87 |
88 |
89 | // --------- utils ------------
90 | function handleError(err) {
91 | console.log(err.toString());
92 | this.emit('end');
93 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gortfolio",
3 | "version": "0.0.0",
4 | "private": true,
5 | "description": "awesome & easy to use portfolio site for Designer / Artist / Developer",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "build": "gulp build",
10 | "watch": "gulp watch",
11 | "serve": "gulp serve"
12 | },
13 | "author": "Eisneim ",
14 | "license": "MIT",
15 | "devDependencies": {
16 | "gulp": "^3.8.11",
17 | "gulp-sass": "^1.2.4",
18 | "gulp-uglify": "~0.2.1",
19 | "gulp-util": "~2.2.14",
20 | "gulp-minify-css": "^0.3.4",
21 | "gulp-autoprefixer": "0.0.7",
22 | "gulp-browserify": "^0.5.1",
23 | "gulp-concat": "^2.5.2",
24 | "gulp-livereload": "^2.1.0",
25 | "gulp-open": "^0.3.2",
26 | "gulp-react": "^2.0.0",
27 | "babel-runtime":"^5.1.11",
28 | "babelify":"^6.0.2"
29 | },
30 | "dependencies": {
31 | "dragdealer": "^0.9.8",
32 | "flux": "^2.0.0",
33 | "lodash": "^3.3.1",
34 | "react": "^0.12.2",
35 | "react-document-title": "^1.0.2",
36 | "react-router": "^0.12.4",
37 | "superagent": "^1.1.0"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/public/app/actions/navActions.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var navConst = require('../constants/commonConst.js').nav ;
3 |
4 | // Define action methods
5 | var navActions = {
6 |
7 | // Receive inital product data
8 | toggle: function( openOrCloseOrToggle ) {
9 | AppDispatcher.handleAction({
10 | actionType: navConst.TOGGLE,
11 | data: openOrCloseOrToggle
12 | })
13 | },
14 |
15 | };
16 |
17 | module.exports = navActions;
18 |
--------------------------------------------------------------------------------
/public/app/actions/portfolioActions.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var portfolioConst = require('../constants/portfolioConst.js') ;
3 |
4 | // Define action methods
5 | var gridActions = {
6 |
7 | // Receive inital product data
8 | receiveData: function( data ) {
9 | AppDispatcher.handleAction({
10 | actionType: portfolioConst.RECEIVE_DATA,
11 | data: data
12 | })
13 | },
14 |
15 | };
16 |
17 | module.exports = navActions;
18 |
--------------------------------------------------------------------------------
/public/app/actions/projectsActions.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var projectsConst = require('../constants/commonConst.js').projects ;
3 |
4 | // Define action methods
5 | var projectsActions = {
6 |
7 | // Receive inital product data
8 | toggleGuide: function( data ) {
9 | AppDispatcher.handleAction({
10 | actionType: projectsConst.TOGGLEGUIDE,
11 | data: data
12 | })
13 | },
14 |
15 | };
16 |
17 | module.exports = projectsActions;
18 |
--------------------------------------------------------------------------------
/public/app/actions/routeCoverActions.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var routeCoverConst = require('../constants/commonConst.js').routeCover ;
3 |
4 | // Define action methods
5 | var navActions = {
6 |
7 | // Receive inital product data
8 | start: function( data ) {
9 | AppDispatcher.handleAction({
10 | actionType: routeCoverConst.START,
11 | data: data
12 | })
13 | },
14 |
15 | finish: function( data ) {
16 | AppDispatcher.handleAction({
17 | actionType: routeCoverConst.FINISH,
18 | data: data
19 | })
20 | },
21 |
22 | };
23 |
24 | module.exports = navActions;
25 |
--------------------------------------------------------------------------------
/public/app/app.js:
--------------------------------------------------------------------------------
1 | var { Link, RouteHandler } = require('react-router');
2 | var RouteCover = require('./components/RouteCover.js');
3 |
4 | var React = require('react');
5 | var PropTypes = React.PropTypes;
6 |
7 | // -------------------- components ---------
8 | var Navtoggle = require('./components/Navtoggle.js');
9 |
10 | var App = React.createClass({
11 | // propTypes: {
12 | // params: PropTypes.object.isRequired,
13 | // query: PropTypes.object.isRequired
14 | // },
15 | componentDidMount: function(){
16 |
17 | },
18 | render: function() {
19 | var navSvg = ' \
20 | ';
21 |
22 | return (
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Intro
34 | Projects
35 | Portfolio
36 | About
37 | Blog
38 | Contact
39 |
40 |
41 |
46 |
Designed with ❤ by Eisneim , this site is opensourced on github
47 |
48 |
49 |
50 |
51 |
52 | );
53 | }
54 |
55 | });
56 |
57 | // ---------- register hash change event to do some transation;
58 | // window.addEventListener("hashchange", onHashChange);
59 | // function onHashChange(e){
60 | // /*
61 | // newURl, oldURL,
62 | // */
63 |
64 | // }
65 |
66 |
67 |
68 |
69 |
70 | module.exports = App;
--------------------------------------------------------------------------------
/public/app/components/Grid.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Grid = React.createClass({
5 | propTypes:{
6 | gridData: React.PropTypes.array.isRequired,
7 | },
8 | getDefaultProps:function(){
9 | return {
10 | gridData: [],
11 | }
12 | },
13 | // getInitialState:function(){
14 |
15 | // },
16 | // componentWillMount: function(){
17 |
18 | // },
19 | componentDidMount: function(){
20 | var wraper = this.getDOMNode();
21 | wraper.style.marginLeft="10px";
22 | wraper.style.width = (window.innerWidth - 20)+'px';
23 | },
24 | componentWillUnmount:function(){
25 |
26 | },
27 | // componentWillReceiveProps:function(nextProps){
28 | // console.log('next props is:');
29 | // console.log(nextProps);
30 | // },
31 | componentDidUpdate:function(){
32 | // store last selection so we can do leaving animation:
33 | this.lastSelected = this.props.selected;
34 | },
35 | render: function(){
36 | var self = this;
37 | var items = [];
38 |
39 | this.props.items.forEach(function(item,index){
40 | var data = self.props.gridData[index] || {};
41 |
42 | var itemStyle = {
43 | width: data.width+ 'px',
44 | height: data.height + 'px',
45 | top: data.top,
46 | left: data.left,
47 | };
48 |
49 | var isSelected = self.props.selected == index;
50 |
51 | if( isSelected ){
52 | var trans = 'translate3d(-50%,-'+(window.innerHeight/2)+'px,0)';
53 | itemStyle = {
54 | width: '100%',
55 | height: window.innerHeight+ 'px',
56 | top: '0',
57 | left: '0',
58 | zIndex: '10',
59 | WebkitTransform: trans,
60 | MozTransform: trans,
61 | msTransform: trans,
62 | OTransform: trans,
63 | transform: trans,
64 | marginTop: (window.innerHeight/2)+'px',
65 | }
66 | }
67 | // this one should leave the sence
68 | if(self.lastSelected == index){
69 | itemStyle.zIndex = '9';
70 | }
71 |
72 | var classname = 'gf-grid-item '+ (isSelected?'full-screen':'');
73 |
74 | items.push(
75 |
76 | {item}
77 |
78 | )
79 |
80 | });
81 |
82 | return (
83 |
84 | {items}
85 |
86 | )
87 | }
88 |
89 | });
90 |
91 | module.exports = Grid;
--------------------------------------------------------------------------------
/public/app/components/Navtoggle.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var navActions = require('../actions/navActions.js');
3 | var navStore = require('../stores/navStore.js')
4 |
5 | var Navtoggle = React.createClass({
6 | _onChange: function() {
7 | // this.setState({});
8 | // console.log('navStore.getState().isNavOpen :'+ navStore.getState().isNavOpen );
9 | if( navStore.getState().isNavOpen ){
10 | this.openNav()
11 | }else{
12 | this.closeNav()
13 | }
14 |
15 | },
16 | componentDidMount: function(){
17 | navStore.addChangeListener(this._onChange);
18 |
19 | // store dom elements here
20 | this.gfelm = {
21 | gfApp:document.getElementById('gf-app'),
22 | navSvgPoints : {
23 | from: [115,800,115,800,115,1,115,1 ],//this.gfelm.navSvgPolygon.attr('points'),
24 | to: [115,800,5 , 800,115,1,115,1 ],//this.gfelm.navSvg.getAttribute('data-points-hover'),
25 | }
26 | }
27 |
28 | this.gfelm.navSvg = Snap( document.getElementById('nav-svg') );//;
29 | this.gfelm.navSvgPolygon = this.gfelm.navSvg.polygon( this.gfelm.navSvgPoints.from );
30 | this.gfelm.navSvgPolygon.attr({
31 | id:"nav-svg-poly",
32 | fill: "#ffffff",
33 | });
34 | this.gfelm.isNavSvgOpen = false;
35 |
36 | // -----create a backdrop overlay ------
37 | this.gfelm.backdrop = document.createElement('div');
38 | this.gfelm.backdrop.id = 'gf-nav-backdrop';
39 | this.gfelm.gfApp.appendChild( this.gfelm.backdrop );
40 | // add event listener to close nav
41 | this.gfelm.backdrop.addEventListener('click',function(e){
42 | navActions.toggle('close');
43 | });
44 |
45 | this._onChange();
46 | },
47 | componentWillUnmount:function(){
48 | navStore.removeChangeListener(this._onChange);
49 | },
50 | openNav:function(){
51 | this.gfelm.gfApp.classList.add('show-nav');
52 | var node = this.getDOMNode();
53 |
54 | node.classList.add('uac-close');
55 | node.classList.add('uac-dark');
56 | this.gfelm.backdrop.style.visibility = 'visible';
57 |
58 | this.gfelm.navSvgPolygon.animate({
59 | 'points': this.gfelm.navSvgPoints.to,
60 | },300, mina.easeinout );
61 | },
62 | closeNav:function(){
63 | var that = this;
64 | this.gfelm.gfApp.classList.remove('show-nav');
65 | var node = this.getDOMNode();
66 |
67 | node.classList.remove('uac-close');
68 | node.classList.remove('uac-dark');
69 |
70 | this.gfelm.backdrop.style.visibility = 'hidden';
71 |
72 | this.gfelm.navSvgPolygon.animate({
73 | 'points': this.gfelm.navSvgPoints.from,
74 | },300, mina.easeinout, function(){
75 |
76 | });
77 | },
78 | // toggleNav:function(){
79 | // this.gfelm.gfApp.classList.toggle('show-nav');
80 | // var node = this.getDOMNode();
81 |
82 | // node.classList.toggle('uac-close');
83 | // node.classList.toggle('uac-dark');
84 |
85 | // this.gfelm.navSvgPolygon.animate({
86 | // 'points': navStore.getState().isNavOpen ? this.gfelm.navSvgPoints.from : this.gfelm.navSvgPoints.to,
87 | // },300, mina.easeinout );
88 | // }
89 | onToggle: function(){
90 | navActions.toggle();
91 | },
92 | render: function(){
93 | var svgString = ' \
94 | \
95 | ';
96 | return (
97 |
102 | )
103 | }
104 | });
105 |
106 | module.exports = Navtoggle;
107 |
--------------------------------------------------------------------------------
/public/app/components/RouteCover.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var routeCoverStore = require('../stores/routeCoverStore.js');
3 | var routeCoverActions = require('../actions/routeCoverActions.js');
4 |
5 | var RouteCover = React.createClass({
6 | _onChange: function() {
7 | // this.setState({});
8 |
9 | var state = routeCoverStore.getState();
10 | if( state.isCoverShown ){
11 | this.start();
12 | }else{
13 | this.finish( );
14 | }
15 |
16 | },
17 | componentDidMount:function(){
18 | routeCoverStore.addChangeListener( this._onChange );
19 | // polygon points
20 | var width = window.innerWidth, height = window.innerHeight;
21 | this.startPoints = [
22 | [0,0, 0,0, 0,height, 0,height ], // 0 start at right;
23 | [0,0, width/4,0, 1,height, 0,height ], // 1
24 |
25 | // [0,0, width/4,0, width/4 ,height, 0,height ], // 2
26 | [0,0, width/4,0, width/2 ,height, 0,height ], // 3
27 |
28 | // [0,0, width/2,0, width/2 ,height, 0,height],
29 | [0,0, width/4*3,0, width/2 ,height, 0,height],
30 |
31 | // [0,0, width/4*3,0, width/4*3 ,height, 0,height],
32 | [0,0, width/4*3,0, width ,height, 0,height],
33 |
34 | [0,0, width,0, width,height, 0,height],//full screen
35 | ];
36 | this.finishPoints = [
37 | [0,0, width,0, width,height, 0,height ],// full screen
38 | [width/4,0, width,0, width,height, 0,height ],
39 | [width,0, width,0, width,height, width/4*3,height ],
40 | [width,0, width,0, width,height, width,height ],
41 | ];
42 |
43 | this.gfelm = {
44 | routeCoverSvg : Snap( document.getElementById('route-cover-svg') ),
45 | };
46 |
47 | this.gfelm.routeCoverPoly= this.gfelm.routeCoverSvg.polygon( this.startPoints[0] );
48 | this.gfelm.routeCoverPoly.attr({
49 | id:"route-cover-poly",
50 | fill: "#fff",
51 | opacity:0.97,
52 | });
53 |
54 | },
55 | start:function(){
56 | // show element
57 | this.getDOMNode().style.display = 'block';
58 | var index = 1;
59 | var that = this;
60 | anim();
61 |
62 | function anim(){
63 | routeCoverStore.setState('isAnimating',true );
64 |
65 | that.gfelm.routeCoverPoly.animate({
66 | 'points': that.startPoints[ index ],
67 | },100, mina.easeinout, function(){
68 | index ++;
69 | if(index < that.startPoints.length ){
70 | // return anim();
71 | setTimeout(anim , 50 );
72 | }
73 | // else{
74 | // // done
75 | // routeCoverStore.setState('isAnimating',false );
76 | // // call finish
77 | // routeCoverActions.finish( );
78 | // }
79 |
80 | } );
81 | }
82 |
83 | },
84 | finish:function( ){
85 | // this func will be called twice, execute at last time
86 | if(routeCoverStore.getState().isAnimating) return;
87 | if(routeCoverStore.getState().isCoverShown ) return;
88 |
89 | var that = this;
90 | this.gfelm.routeCoverPoly.animate({'points': this.finishPoints[ 1 ],},80, mina.easeinout,function(){
91 | that.gfelm.routeCoverPoly.animate({'points': that.finishPoints[ 2 ],},300, mina.easeinout,function(){
92 | that.gfelm.routeCoverPoly.animate({'points': that.finishPoints[ 3 ],},80, mina.easeinout,function(){
93 | that.gfelm.routeCoverPoly.attr({
94 | points: that.startPoints[0],
95 | });
96 | // and hide element
97 | that.getDOMNode().style.display = 'none';
98 | })
99 | })
100 |
101 | } )
102 |
103 |
104 | },
105 | render: function(){
106 | var width = window.innerWidth, height = window.innerHeight;
107 | var svgString = ' \
108 | ';
109 | return (
110 |
111 |
112 | )
113 | }
114 | });
115 |
116 | module.exports = RouteCover;
--------------------------------------------------------------------------------
/public/app/components/Typer.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var Typer = React.createClass({
4 | propTypes:{
5 | words: React.PropTypes.string.isRequired
6 | },
7 | getDefaultProps:function(){
8 | return {
9 | words: 'Web Design||Art',
10 | }
11 | },
12 | componentDidMount: function(){
13 | var $wraper = this.getDOMNode();
14 | $wraper.classList.add('uac-waiting');
15 |
16 | var $words = $wraper.getElementsByTagName('b');
17 |
18 | var _duration = 3000;
19 | var animationDuration = 1200;// in and out duration;
20 | var letterAnimDelay = 80;
21 |
22 | var activeWordIndex=0,$current = $words[0],$previous, $next;
23 |
24 | var letterInInterval = setInterval(function(){
25 | letterIn($current.childNodes );
26 | },100 );;
27 |
28 | this.wordTimer = setInterval(function(){
29 | if(letterInInterval) clearInterval( letterInInterval );
30 |
31 | if(activeWordIndex >= $words.length ) activeWordIndex = 0;
32 | $current = getByIndex($words, activeWordIndex );
33 | $previous = getByIndex($words, activeWordIndex - 1 );
34 | $next = getByIndex($words, activeWordIndex +1 );
35 |
36 | $current.classList.remove('uac-hidden');
37 | $current.classList.add('uac-visible');
38 |
39 | $previous.classList.remove('uac-visible');
40 | $previous.classList.add('uac-hidden');
41 |
42 | // ----------letterery
43 | $wraper.classList.remove('uac-waiting');
44 | setTimeout(function(){
45 | // select words
46 | $wraper.classList.add('uac-selected');
47 | } , _duration - 500 );
48 |
49 | letterInInterval = setInterval(function(){
50 | letterIn($current.childNodes );
51 | },letterAnimDelay );
52 |
53 | letterOut( $previous.childNodes );
54 |
55 | activeWordIndex ++;
56 | }, _duration );
57 |
58 | // sequencially add .uac-in and .uac-out to letters
59 | var inLetterIndex = 0, outLetterIndex = 0;
60 | function letterIn(letters){
61 |
62 | $wraper.classList.remove('uac-selected');
63 |
64 | if(letters[inLetterIndex]){
65 | letters[inLetterIndex].classList.remove('uac-out');
66 | letters[inLetterIndex].classList.add('uac-in');
67 | }
68 |
69 | inLetterIndex++;
70 | if( inLetterIndex < letters.length ) {
71 | return;
72 | }else{ // finished all letter animation , now waitting for next
73 | inLetterIndex = 0;
74 | // flicker effect
75 | $wraper.classList.add('uac-waiting');
76 | clearInterval( letterInInterval );
77 | }
78 | }
79 |
80 | function letterOut(letters){
81 | // hide all at onece;
82 | for(var ii=0;ii= arr.length ){
89 | return arr[0];
90 | }else if( index < 0 ){
91 | return arr[ arr.length-1 ];
92 | }else{
93 | return arr[index];
94 | }
95 | };
96 |
97 |
98 | },
99 | componentWillUnmount:function(){
100 | clearInterval(this.wordTimer);
101 | },
102 | render: function(){
103 | var words = this.props.words.split('||');
104 | var wordElms = words.map(function(word,index){
105 | var chars = [];
106 | var classString = index == 0 ? 'uac-visible' : '';
107 | for(var ii=0;ii{word[ii]} );
109 | }
110 | return { chars}
111 | });
112 |
113 | return (
114 |
115 | {wordElms}
116 |
117 | )
118 | }
119 |
120 | });
121 |
122 | module.exports = Typer;
--------------------------------------------------------------------------------
/public/app/constants/commonConst.js:
--------------------------------------------------------------------------------
1 | var keyMirror = require('react/lib/keyMirror');
2 |
3 | // Define action constants
4 | module.exports = {
5 | routeCover: keyMirror({
6 | START: null,
7 | FINISH: null,
8 | }),
9 |
10 | nav: keyMirror({
11 | TOGGLE: null
12 | }),
13 |
14 | projects: keyMirror({
15 | TOGGLEGUIDE: null
16 | }),
17 |
18 | }
--------------------------------------------------------------------------------
/public/app/constants/portfolioConst.js:
--------------------------------------------------------------------------------
1 | var keyMirror = require('react/lib/keyMirror');
2 |
3 | // Define action constants
4 | module.exports = keyMirror({
5 | RECEIVE_DATA: null,
6 | RESIZE:null,
7 | });
8 |
--------------------------------------------------------------------------------
/public/app/constants/projectsConst.js:
--------------------------------------------------------------------------------
1 | var keyMirror = require('react/lib/keyMirror');
2 |
3 | // Define action constants
4 | module.exports = keyMirror({
5 | RECEIVE_DATA: null
6 | });
7 |
--------------------------------------------------------------------------------
/public/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | // Create dispatcher instance
4 | var AppDispatcher = new Dispatcher();
5 |
6 | // Convenience method to handle dispatch requests
7 | AppDispatcher.handleAction = function(action) {
8 | this.dispatch({
9 | source: 'VIEW_ACTION',
10 | action: action
11 | });
12 | }
13 |
14 | module.exports = AppDispatcher;
15 |
--------------------------------------------------------------------------------
/public/app/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | ___ _ _
3 | _ / __) | |(_)
4 | ____ ___ ____ _| |_ _| |__ ___ | | _ ___
5 | / _ |/ _ \ / ___|_ _|_ __) _ \| || |/ _ \
6 | ( (_| | |_| | | | |_ | | | |_| | || | |_| |
7 | \___ |\___/|_| \__) |_| \___/ \_)_|\___/
8 | (_____|
9 |
10 | ================================================
11 | author: eisneim
12 |
13 | */
14 |
15 |
16 | 'use strict';
17 | var React = require('react');
18 | var Router = require('react-router');
19 | var routes = require('./routes.js');
20 |
21 | var navActions = require('./actions/navActions.js');
22 | var routeCoverActions = require('./actions/routeCoverActions.js');
23 | var request = require('superagent');
24 |
25 | /**
26 | * first run don't have anything rendered on page, so it is special,
27 | * we can do some initial load animation
28 | */
29 | var isFirstRun = true;
30 |
31 | /**
32 | * !!! bad hacky way here!!!, backend is not done yet ,so i'll just put some shared data here
33 | */
34 | var sharedData = {};
35 | /**
36 | * some routes have mananl leaving animation, below are some top level routes
37 | * that need auto add leaving anition;
38 | */
39 | var leaveAnimRoutes = ['intro','about','ideas','contact'];
40 | /**
41 | * some of the routes need to preload a lot of stuff
42 | * so we need to proveide longer route transition animation;
43 | */
44 | var longLoad = ['projects','portfolio'];
45 | var noLoadFromThose = ['portfolioItem','project'];
46 |
47 | var loadUrl = {
48 | projects: 'data/projects.json',
49 | portfolio: 'data/portfolio.json',
50 | project: 'data/projects.json',
51 | portfolioItem: 'data/portfolio.json',
52 | }
53 |
54 | var previousRoute;
55 | /**
56 | * we have route transtion animation on long load routes,
57 | * for those routes:
58 | * when route change start ,start a timer that have the shortest lenght to finish animation
59 | * shouldRouteTransionDone == true only when both animtion and xhr request both finished
60 | */
61 | var xhrLoadDone,routeAnimationDone;
62 |
63 | Router.run(routes,function(Handler,state) {
64 | var routeName = state.routes[ state.routes.length-1 ].name ;
65 |
66 | /**
67 | * 每当路由改变,这里都会运行一次,可以在这里检查那些需要载入动画,以及关闭侧栏;
68 | */
69 | navActions.toggle('close');
70 |
71 | if( longLoad.indexOf( routeName ) > -1 && noLoadFromThose.indexOf(previousRoute) == -1 ){
72 | var preloadedData;
73 |
74 | routeCoverActions.start();
75 | // set a minimal length to make sure animation is done;
76 | setTimeout( function(){
77 | routeAnimationDone = true;
78 | renderLongLoadRoute(Handler,state,preloadedData);
79 | }, isFirstRun?0:900)
80 |
81 | longLoadInterceptor( routeName, function(req,res){
82 | preloadedData = res.body;
83 |
84 | xhrLoadDone = true;
85 | renderLongLoadRoute(Handler,state,preloadedData);
86 |
87 | });
88 |
89 | }else if( leaveAnimRoutes.indexOf( routeName ) > -1 ){
90 | var $view = document.querySelector('.gf-view');
91 | if($view) $view.classList.add('fade-out');
92 | setTimeout(function(){
93 | React.render(, document.body );
94 | },300);
95 | }else if( loadUrl[routeName] ){
96 | request.get( loadUrl[routeName] ).end(function(req,res){
97 | React.render(, document.body );
98 | });
99 | }else{
100 |
101 | React.render(, document.body );
102 | }
103 | /**
104 | * record previus route so we can have more controll;
105 | */
106 | previousRoute = routeName;
107 | if(isFirstRun) isFirstRun = false;
108 | });
109 |
110 | function longLoadInterceptor(routeName , callback){
111 | var url = loadUrl[routeName];
112 | if(url){
113 | request.get(url).end(callback)
114 | }else{
115 | setTimeout(callback,800);
116 | }
117 | }
118 |
119 | function renderLongLoadRoute(Handler,state, preloadedData){
120 | if( xhrLoadDone && routeAnimationDone) {
121 | React.render(, document.body );
122 | // hide animation;
123 | routeCoverActions.finish();
124 | // for next route cahgne
125 | xhrLoadDone = false;
126 | routeAnimationDone = false;
127 | }
128 | }
--------------------------------------------------------------------------------
/public/app/pages/About.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Router = require('react-router');
3 | /*
4 | this is about page
5 | {this.getPathname()}
6 | this.getRoutes() : {this.getRoutes()}
7 | this.getParams(): {this.getParams()}
8 | this.getQuery(): {this.getQuery()}
9 |
10 | */
11 | var About = React.createClass({
12 | mixins: [ Router.State ],
13 | render: function(){
14 | return (
15 |
16 |
17 |
18 |
19 |
ABOUT.ME.
20 |
GREETINGS.
21 |
Hi there. I am Eisneim Terry(made in 1991), Shanghai based Digital artist & Developer. I'm currently work at startup project xinpingzi.com as lead web developer.
22 | And, here glexe.com is my personal space to memorize my workpieces and memories of the enjoyment of creating beautiful things.
23 |
24 |
25 | My university degree is Bachelor in Electronic Engineering, but I taught myself a lot more than electronics.
26 | Great thanks to the Internet, I learned almost all my skills online from: Youtube, Vimeo,
27 | lynda.com ,
28 | tutsplus.com ,
29 | pluralsight.com ,
30 | DigitalTutors.com , and many many more.
31 | I record and share free video tutorials as well, you can find them on zexeo.com
32 |
33 |
34 |
WHAT I love to DO.
35 |
MotionGraphics, VFX, Web Development, Digital Paint, Parkour, BodyBuilding
36 |
37 |
SKILL SETS.
38 |
39 | Design & Motion & VFX : After Effects, Cinema 4D, Nuke, Illustrator, Photoshop, MochaPro, Premiere
40 | Web ServerSide : Node.JS, Golang, MongoDB, PHP
41 | Web ClientSide : Angular.JS, React.JS, SVG, Javascript, CSS3, HTML5
42 |
43 |
44 |
Stay in touch →
45 |
46 |
47 |
48 | )
49 | }
50 | });
51 |
52 | module.exports = About;
--------------------------------------------------------------------------------
/public/app/pages/Contact.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Navigation = require('react-router').Navigation;
3 | var request = require('superagent');
4 |
5 | var Contact = React.createClass({
6 | // mixins: [Navigation],
7 | getInitialState:function(){
8 | return {
9 | formError:null,
10 | formInfo:null,
11 | }
12 | },
13 | handleSubmit:function(e){
14 | e.preventDefault();
15 | var formData = {
16 | message: this.refs.messageInput.getDOMNode().value,
17 | email: this.refs.emailInput.getDOMNode().value,
18 | }
19 |
20 | if(!formData.message || !formData.email){
21 | return this.setState({
22 | formError:'Please fillin valid data in, so i can contact you back.',
23 | })
24 | }
25 |
26 | request.post('/message')
27 | .set('Content-Type', 'application/json')
28 | .withCredentials()
29 | .send(formData)
30 | .end(function(req,res){
31 | console.log(res.status)
32 | // reset form
33 | e.target.reset();
34 | this.setState({
35 | formError:null,
36 | formInfo:'Thnak you! you have successfully send me a message!',
37 | })
38 |
39 | });
40 | },
41 | handleBlur:function(e){
42 | if(e.target.value){
43 | e.target.parentNode.classList.add('filled');
44 | }else{
45 | e.target.parentNode.classList.remove('filled');
46 | }
47 | },
48 | render: function(){
49 | return (
50 |
72 | )
73 | /*
74 |
103 | */
104 | }
105 | });
106 |
107 | module.exports = Contact;
--------------------------------------------------------------------------------
/public/app/pages/Ideas.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var Ideas = React.createClass({
4 | render: function(){
5 | return (
6 |
7 |
8 |
this is Ideas page
9 |
10 |
11 |
12 | )
13 | }
14 | });
15 |
16 | module.exports = Ideas;
--------------------------------------------------------------------------------
/public/app/pages/Intro.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Typer = require('../components/Typer.js');
3 |
4 | var Intro = React.createClass({
5 | // componentDidMount:function(){
6 | // // let's insert our big backgournd video;
7 |
8 | // },
9 | render: function(){
10 | return (
11 |
12 |
24 |
25 |
26 |
27 |
28 | your browser is way too old!
29 |
30 |
31 | )
32 | }
33 | });
34 |
35 | module.exports = Intro;
--------------------------------------------------------------------------------
/public/app/pages/Portfolio.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Grid = require('../components/Grid.js');
3 | var Router = require('react-router');
4 | var RouteHandler = Router.RouteHandler;
5 | var gridSvc = require('../service/gridSvc6.js');
6 | var _ = require('lodash');
7 | var request = require('superagent');
8 | /**
9 | * TODO:
10 | * 1.filter by type: video,illustration,design etc.
11 | */
12 |
13 | var Portfolio = React.createClass({
14 | mixins: [
15 | Router.Navigation,
16 | Router.State
17 | ],
18 | getInitialState: function(){
19 | var items = this.props.preload;
20 |
21 | this.grid = gridSvc({
22 | gridWidth: window.innerWidth - 40,
23 | minItemWidth:280,
24 | itemLength: items.length,
25 | });
26 |
27 | var gridData = this.grid.fill();
28 | return {
29 | items: items,
30 | gridData: gridData,
31 | }
32 | },
33 | componentWillMount: function(){
34 |
35 | },
36 | componentDidMount:function(){
37 | var self = this;
38 | this.debouncedFill = _.debounce( this.refill , 200);
39 | // add window resize event listener
40 | window.addEventListener('resize', this.debouncedFill );
41 |
42 | this.elms = {
43 | self: this.getDOMNode(),
44 | portfolioItem: document.getElementById('gf-portfolio-item'),
45 | }
46 | },
47 | componentWillUnmount:function(){
48 | // remove grid resize listener
49 | window.removeEventListener('resize',this.debouncedFill );
50 |
51 | },
52 | refill:function(){
53 | var gridData = this.grid.refill();
54 |
55 |
56 | this.setState({
57 | gridData: gridData,
58 | });
59 | },
60 | /**
61 | * when portfolio item is selected, page will scroll to top
62 | * @return void
63 | */
64 | scrollPosition:function(){
65 | var self = this;
66 | if(!this.elms || !this.elms.self) return;
67 | if(this.lastScrollPosition && this.lastScrollPosition > 200){
68 | setTimeout(function(){
69 | self.elms.self.scrollTop = self.lastScrollPosition;
70 | console.log( self.lastScrollPosition );
71 | },100);
72 | }
73 |
74 | if(this.elms.self.scrollTop >= 200){
75 | this.lastScrollPosition = this.elms.self.scrollTop;
76 | }
77 |
78 | },
79 | render: function(){
80 | // this.scrollPosition();
81 |
82 | var sectionClasses = 'gf-view';
83 | var itemWraperClass = '';
84 |
85 | var items = [],selected, selectedItem = this.getParams().itemName;
86 | if( selectedItem ){
87 | sectionClasses+= ' showItem';
88 | itemWraperClass += ' show';
89 | }
90 |
91 | this.state.items.forEach(function(item,index){
92 | var style = {
93 | backgroundImage: 'url('+item.thumbnail+')',
94 | };
95 | if(item.url == selectedItem) selected = index;
96 | var itemid = 'gf-'+item.url;
97 |
98 | items.push(
99 |
100 |
101 |
{item.name}
102 |
{item.description}
103 |
104 |
105 |
106 | )
107 | });
108 |
109 | return (
110 |
120 | );
121 | }
122 | }); // createClass
123 |
124 |
125 | module.exports = Portfolio;
--------------------------------------------------------------------------------
/public/app/pages/PortfolioItem.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Router = require('react-router');
3 | var _ = require('lodash');
4 | var request = require('superagent');
5 |
6 | var Item = React.createClass({
7 | // mixins: [Navigation],
8 | mixins: [Router.State],
9 | statics:{
10 | // scen enter animation
11 | willTransitionTo: function(transition, params) {
12 |
13 | },
14 | // leave animation
15 | willTransitionFrom: function(transition, component ) {
16 |
17 | },
18 | },
19 | getInitialState:function(){
20 | return {
21 | item: this.props.item,
22 | }
23 | },
24 | componentWillMount:function(){
25 | },
26 | componentDidMount:function(){
27 | var self = this;
28 |
29 | request.get('data/portfolio/'+self.props.item.url+'.html')
30 | .end(function(req,res){
31 | var item = _.extend( self.props.item );
32 | item.content = res.text;
33 | self.setState({
34 | item: item,
35 | })
36 | })
37 |
38 | },
39 | render: function(){
40 | var item = this.state.item || {};
41 | var headerStyle = {
42 | backgroundImage: 'url('+item.cover+')',
43 | width:100+'%',
44 | height: 100+'vh',
45 | }
46 |
47 | return (
48 |
54 | )
55 | }
56 | });
57 |
58 | module.exports = Item;
--------------------------------------------------------------------------------
/public/app/pages/Project.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Router = require('react-router');
3 | var request = require('superagent');
4 | var _ = require('lodash');
5 |
6 | var Project = React.createClass({
7 | // mixins: [Navigation],
8 | mixins: [Router.State],
9 | // statics:{
10 | // // scen enter animation
11 | // willTransitionTo: function (transition, params) {
12 |
13 | // },
14 | // // leave animation
15 | // willTransitionFrom: function(transition, component ){
16 |
17 | // },
18 | // },
19 | // getInitialState:function(){
20 | // return {
21 | // // isFullscreen: false,
22 | // }
23 | // },
24 | getInitialState:function(){
25 | return {
26 | projectData: this.props.projectData,
27 | }
28 | },
29 | componentDidMount:function(){
30 | var node = this.getDOMNode();
31 | setTimeout(function(){
32 | node.style.opacity = 1;
33 | },500);
34 |
35 | var self = this;
36 |
37 | request.get('data/projects/'+self.props.projectData.url+'.html')
38 | .end(function(req,res){
39 | var projectData = _.extend( self.props.projectData );
40 | projectData.content = res.text;
41 | self.setState({
42 | projectData: projectData,
43 | })
44 | })
45 | },
46 | // componentWillUnmount:function(){
47 |
48 | // },
49 | leaveSence:function(){
50 | // this.elm.dragwraper.style.transform = 'translateX(-'+( that.ui.currentSlide /that.elm.slides.length * 100)+'%)';
51 | // this.getDOMNode().classList.add('gf-leave');
52 | },
53 | render: function(){
54 | var projectData = this.state.projectData || {};
55 | return (
56 |
60 | )
61 | }
62 | });
63 |
64 | module.exports = Project;
--------------------------------------------------------------------------------
/public/app/pages/Projects.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Router = require('react-router');
3 | var RouteHandler = Router.RouteHandler;
4 | var Navigation = Router.Navigation;
5 | var Dragdealer = require('dragdealer').Dragdealer;
6 | var navActions = require('../actions/navActions.js');
7 | var request = require('superagent');
8 |
9 | var projectsStore = require('../stores/projectsStore.js');
10 | var projectsActions = require('../actions/projectsActions.js');
11 |
12 | var projects = null;
13 |
14 | var Projects = React.createClass({
15 | mixins: [Navigation,Router.State],
16 | statics:{
17 | // scen enter animation
18 | willTransitionTo: function (transition, params) {
19 | },
20 | // leave animation
21 | willTransitionFrom: function(transition, component ){
22 | // close side navigation;
23 | // navActions.toggle('close');
24 | // // start leave animation;
25 | // component.leaveSence();
26 |
27 | // setTimeout(function(){
28 | // component.leaveAnimationDone = true;
29 | // transition.retry();
30 | // },500);
31 | // if(!component.leaveAnimationDone){
32 | // transition.abort();
33 | // }
34 | },
35 | },
36 | _onChange: function() {
37 | this.setState( projectsStore.getState() );
38 | },
39 | getInitialState:function(){
40 | return {
41 | // showAll: false,
42 | projects: this.props.preload,
43 | showGuide: projectsStore.getState().showGuide ,
44 | ui:{
45 | showAll:false,
46 | currentSlide: 0,
47 | }
48 |
49 | }
50 | },
51 | componentDidMount:function(){
52 | projectsStore.addChangeListener( this._onChange );
53 |
54 |
55 | this.ui = {
56 | showAll:false,
57 | currentSlide: 0,
58 | },
59 | this.elm = {
60 | slides: [].slice.call( document.getElementById('gf-projects-wraper').children ),
61 | dragwraper: document.getElementById('gf-projects-wraper'),
62 | };
63 | this.elm.slides[0].classList.add('active');
64 |
65 | this._initDrag();
66 | this._initEvents();
67 |
68 | // if(this.state.activePorject){
69 | // this.showProject();
70 | // }
71 | },
72 | componentWillUnmount:function(){
73 | document.removeEventListener( 'keydown', this.keyEventHandler );
74 | },
75 | _initDrag: function(){
76 | var that = this;
77 | this.dd = new Dragdealer('gf-projects-drag', {
78 | steps: this.props.preload.length,
79 | speed: 0.3,
80 | loose: true,
81 | requestAnimationFrame: true,
82 | callback: function( x, y ) {
83 | // console.log( self.dd.getStep() );
84 | that.ui.currentSlide = that.dd.getStep()[0]-1;
85 | // update class of curren active slide;
86 | for(var ii =0;ii< that.elm.slides.length; ii++){
87 | that.elm.slides[ii].classList.remove('active');
88 | };
89 | that.elm.slides[ that.ui.currentSlide].classList.add('active');
90 | // change transform orgin
91 |
92 | }
93 | });
94 | },
95 | _initEvents:function(){
96 | var self = this;
97 | this.elm.slides.forEach( function( slide ) {
98 | // clicking the slides when not in showAll mode
99 | slide.addEventListener( 'click', function(e) {
100 | if(e.target.tagName == 'A') {
101 | if( e.target.className.indexOf('gf-project-link') > -1 ){
102 | // self.showProject();
103 | }
104 | return;
105 | }
106 |
107 | if( !self.ui.showAll || self.dd.activity ) return false;
108 |
109 | if( self.elm.slides.indexOf( slide ) === (self.ui.currentSlide) ) {
110 | self.onToggleView();
111 | }else {
112 | self.dd.setStep( self.elm.slides.indexOf( slide ) + 1 );
113 | }
114 | } );
115 |
116 | } );
117 | this.keyEventHandler = function( ev ) {
118 | var keyCode = ev.keyCode || ev.which,
119 | currentSlide = self.elm.slides[ self.ui.currentSlide ];
120 |
121 | switch (keyCode) {
122 | case 40: // down key
123 | if( self.ui.showAll ){
124 | // should to to poject page:
125 | self.transitionTo('project',{
126 | projectUrl: self.props.preload[ self.ui.currentSlide ].url,
127 | });
128 |
129 | return;
130 | };
131 | self.onToggleView( currentSlide );
132 | break;
133 | //up
134 | case 38:
135 | // if not fullscreen don't reveal the content. If you want to navigate directly to the content then remove this check.
136 | if( !self.ui.showAll ) return;
137 | self.onToggleView( currentSlide );
138 | break;
139 | // left;
140 | case 37:
141 | self.dd.setStep( self.ui.currentSlide - 1 );
142 | break;
143 | case 39:
144 | // righ
145 | self.dd.setStep( self.ui.currentSlide + 2 );
146 | break;
147 | }
148 | };
149 | // keyboard navigation events
150 | document.addEventListener( 'keydown', this.keyEventHandler );
151 |
152 | },
153 | onToggleView:function(){
154 | var that = this;
155 | this.getDOMNode().classList.toggle('gf-showall');
156 | that.dd.disable();
157 | // reculculate translateX
158 | this.elm.dragwraper.style.transform = 'translateX(-'+( that.ui.currentSlide /that.elm.slides.length * 100)+'%)';
159 |
160 | setTimeout(function(){
161 | that.dd.reflow();
162 | that.dd.enable();
163 | that.ui.showAll = !that.ui.showAll;
164 | },520);
165 | },
166 | componentDidUpdate:function(){
167 | var self = this;
168 | // recalculate for dragdealer
169 | setTimeout(function(){
170 | self.dd.reflow();
171 | },100);
172 |
173 | if( this.getParams().projectUrl ){
174 | this.getDOMNode().classList.add('gf-leave')
175 | // remove event handler
176 | document.removeEventListener( 'keydown', this.keyEventHandler );
177 |
178 | }else{
179 | this.getDOMNode().classList.remove('gf-leave')
180 | document.addEventListener( 'keydown', this.keyEventHandler );
181 | }
182 |
183 | },
184 | leaveSence:function(){
185 | // this.elm.dragwraper.style.transform = 'translateX(-'+( that.ui.currentSlide /that.elm.slides.length * 100)+'%)';
186 |
187 | // this.getDOMNode().classList.add('gf-leave');
188 | // var self = this;
189 | // setTimeout(function(){
190 | // var $drag = document.getElementById('gf-projects-drag');
191 | // if($drag) $drag.style.display = 'none';
192 | // },1000);
193 | },
194 | /**
195 | * show a specific project and hide dragable gird;
196 | */
197 | showProject:function(){
198 | this.leaveSence();
199 |
200 | },
201 | render: function(){
202 | var self = this;
203 | var projects = this.props.preload;
204 |
205 | var projectElms = [];
206 | var selectedProject = null;
207 | var activePorject = this.getParams().projectUrl;
208 |
209 | projects.forEach(function(pp ,index ){
210 | var projectStyle = {
211 | 'backgroundImage': 'url('+pp.cover+')',
212 | 'width': (100/projects.length)+'%'
213 | };
214 |
215 | if( activePorject == pp.url ) selectedProject = projects[index];
216 |
217 | projectElms.push(
218 |
219 |
220 |
221 |
{pp.description}
222 |
223 |
224 |
{pp.name}
225 |
226 |
227 |
228 | )
229 | });
230 | var classese = 'gf-view '+( activePorject ? 'gf-leave':'');
231 |
232 | return (
233 |
234 |
235 |
236 |
237 |
238 |
Interactions
239 | Drag Sliders
240 | Use Arrows
241 | Switch view
242 | Got it!
243 |
244 |
245 |
246 |
247 |
248 |
249 | {projectElms}
250 |
251 |
252 |
253 |
254 |
255 | )
256 | }
257 | });
258 |
259 | module.exports = Projects;
--------------------------------------------------------------------------------
/public/app/routes.js:
--------------------------------------------------------------------------------
1 | var React = require('react'),
2 | Router = require('react-router'),
3 | Route = Router.Route ,
4 | DefaultRoute = Router.DefaultRoute,
5 | App = require('./App.js'),
6 | Intro = require('./pages/Intro.js'),
7 | Projects = require('./pages/Projects.js'),
8 | Project = require('./pages/Project.js'),
9 | About = require('./pages/About.js'),
10 | Portfolio = require('./pages/Portfolio.js'),
11 | PortfolioItem = require('./pages/PortfolioItem.js'),
12 | Ideas = require('./pages/Ideas.js'),
13 | Contact = require('./pages/Contact.js');
14 |
15 | module.exports = (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 |
31 |
--------------------------------------------------------------------------------
/public/app/service/gridSvc.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | /**
3 | * Grid item type
4 | * ---- -------- ---- --------
5 | * | | | | | | | |
6 | * | | | | | | | |
7 | * | | | |
8 | * | | | |
9 | * 1 2 3 4
10 | * 1.base squre
11 | * 2.width>height, width == 2*base
12 | * 3.height>width,
13 | * 4. width == 2*base, height == 2*base
14 | */
15 |
16 | function Grid(opt) {
17 |
18 | // options
19 | this.itemLength = opt.itemLength;
20 | this.gridWidth = opt.gridWidth || opt.gridWidth;
21 | this.minItemWidth = opt.minItemWidth || 200;
22 | this.gutter = opt.gutter || 10;
23 |
24 | };
25 |
26 | Grid.prototype.setUp = function() {
27 | /**
28 | * setting up the virtual grid
29 | */
30 | this.virtual = [];
31 |
32 | this.columns = Math.floor(this.gridWidth / this.minItemWidth);
33 | this.baseWidth = this.gridWidth / this.columns - this.gutter;
34 |
35 | var row = Math.ceil(this.itemLength * 4 / this.columns);
36 | for (var ii = 0; ii < row; ii++) {
37 | var rowOfItems = [];
38 | for (var jj = 0; jj < this.columns; jj++) {
39 | rowOfItems.push({
40 | top: ii * (this.baseWidth + this.gutter), // y value
41 | left: jj * (this.baseWidth + this.gutter), // x value
42 | isOccupied: false,
43 | });
44 | }
45 | this.virtual.push(rowOfItems);
46 | }; // end of outter for loop
47 | // pointer of virtual grid
48 | this.currentRow = 0;
49 | this.currentColumn = 0;
50 | this.currentType = 1;
51 |
52 | console.log('total colums:' + this.columns);
53 | console.log('baseWidth:' + this.baseWidth);
54 | }
55 |
56 | Grid.prototype.checkSize = function(type, col) {
57 | if (type == 2 || type == 4) {
58 | var isOutofEdge = (col + 1) > this.columns;
59 | var isCoverOther = true;
60 | if ((col + 1) < this.columns) {
61 | isCoverOther = this.virtual[this.currentRow][col + 1].isOccupied;
62 | }
63 |
64 | return !isOutofEdge && !isCoverOther;
65 |
66 | } else {
67 | return true;
68 | }
69 |
70 | }
71 | Grid.prototype.walkVirtualGrid = function() {
72 | var col = this.currentColumn;
73 | var row = this.currentRow;
74 | var totalCol = this.columns;
75 |
76 | // first check if this one is occupied
77 | while (this.virtual[row][col].isOccupied) {
78 | col++;
79 | if (col >= this.columns) {
80 | col = 0;
81 | row++;
82 | }
83 | // console.log('col:'+col);
84 | // console.log('row:'+row);
85 | }
86 | // check if this item fit in;
87 | while (!this.checkSize(this.currentType, col)) {
88 | this.currentType = Math.ceil(Math.random() * 2) * 2 - 1; // 1, 3
89 |
90 | // console.log('currentType is:'+ this.currentType );
91 | }
92 |
93 | var itemType = this.currentType;
94 |
95 | var startVirtualItem = this.virtual[row][col];
96 |
97 | switch (itemType) {
98 | case 1:
99 | this.virtual[row][col].isOccupied = true;
100 | col++;
101 | break;
102 | case 2:
103 | this.virtual[row][col].isOccupied = true;
104 | this.virtual[row][col + 1].isOccupied = true;
105 | col += 2;
106 | break;
107 | case 3:
108 | this.virtual[row][col].isOccupied = true;
109 | this.virtual[row + 1][col].isOccupied = true;
110 |
111 | col++;
112 | break;
113 | case 4:
114 | this.virtual[row][col].isOccupied = true;
115 | this.virtual[row][col + 1].isOccupied = true;
116 | this.virtual[row + 1][col].isOccupied = true;
117 | this.virtual[row + 1][col + 1].isOccupied = true;
118 |
119 | col += 2;
120 | break;
121 | };
122 |
123 | if (col >= this.columns) {
124 | col = 0;
125 | row++;
126 | }
127 |
128 |
129 | this.currentColumn = col;
130 | this.currentRow = row;
131 |
132 | return startVirtualItem;
133 | },
134 | Grid.prototype.positionOneItem = function() {
135 | this.currentType = Math.ceil(Math.random() * 4);
136 |
137 | var virtualItem = this.walkVirtualGrid();
138 |
139 | // console.log(virtualItem);
140 |
141 | return {
142 | top: virtualItem.top,
143 | left: virtualItem.left,
144 | }
145 | },
146 |
147 | Grid.prototype.fill = function() {
148 | var self = this;
149 |
150 | this.setUp();
151 |
152 | var itemStyles = [];
153 | for (var ii = 0; ii < this.itemLength; ii++) {
154 | var pos = self.positionOneItem();
155 |
156 | var width, height;
157 | switch (self.currentType) {
158 | case 1:
159 | width = self.baseWidth;
160 | height = self.baseWidth;
161 | break;
162 | case 2:
163 | width = self.baseWidth * 2 + self.gutter;
164 | height = self.baseWidth;
165 | break;
166 | case 3:
167 | width = self.baseWidth;
168 | height = self.baseWidth * 2 + self.gutter;
169 | break;
170 | case 4:
171 | width = self.baseWidth * 2 + self.gutter;
172 | height = self.baseWidth * 2 + self.gutter;
173 | break;
174 | }
175 |
176 | var itemStyle = {
177 | width: width,
178 | height: height,
179 | top: pos.top,
180 | left: pos.left,
181 | };
182 |
183 | itemStyles.push(itemStyle);
184 |
185 | }; // end of for
186 | return itemStyles;
187 | }
188 | Grid.prototype.refill = function(){
189 | this.gridWidth = window.innerWidth - 20;
190 | return this.fill();
191 | }
192 |
193 | Grid.prototype.deBouncedRefill = function(){
194 | return _.debounce( this.refill.bind(this) , 200);
195 | }
196 |
197 |
198 |
199 | module.exports = function(option) {
200 | return new Grid(option);
201 | }
--------------------------------------------------------------------------------
/public/app/service/gridSvc6.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | /**
3 | * Grid item type
4 | * ---- -------- ---- --------
5 | * | | | | | | | |
6 | * | | | | | | | |
7 | * | | | |
8 | * | | | |
9 | * 1 2 3 4
10 | * 1.base squre
11 | * 2.width>height, width == 2*base
12 | * 3.height>width,
13 | * 4. width == 2*base, height == 2*base
14 | */
15 |
16 | class Grid {
17 | constructor( opt ){
18 | // options
19 | this.itemLength = opt.itemLength;
20 | this.gridWidth = opt.gridWidth || opt.gridWidth;
21 | this.minItemWidth = opt.minItemWidth || 200;
22 | this.gutter = opt.gutter || 10;
23 | }
24 |
25 | setUp() {
26 | /**
27 | * setting up the virtual grid
28 | */
29 | this.virtual = [];
30 |
31 | this.columns = Math.floor(this.gridWidth / this.minItemWidth);
32 | this.baseWidth = this.gridWidth / this.columns - this.gutter;
33 |
34 | var row = Math.ceil(this.itemLength * 4 / this.columns);
35 | for (var ii = 0; ii < row; ii++) {
36 | var rowOfItems = [];
37 | for (var jj = 0; jj < this.columns; jj++) {
38 | rowOfItems.push({
39 | top: ii * (this.baseWidth + this.gutter), // y value
40 | left: jj * (this.baseWidth + this.gutter), // x value
41 | isOccupied: false,
42 | });
43 | }
44 | this.virtual.push(rowOfItems);
45 | }; // end of outter for loop
46 | // pointer of virtual grid
47 | this.currentRow = 0;
48 | this.currentColumn = 0;
49 | this.currentType = 1;
50 |
51 | console.log('total colums:' + this.columns);
52 | console.log('baseWidth:' + this.baseWidth);
53 | }
54 |
55 | checkSize (type, col) {
56 | if (type == 2 || type == 4) {
57 | var isOutofEdge = (col + 1) > this.columns;
58 | var isCoverOther = true;
59 | if ((col + 1) < this.columns) {
60 | isCoverOther = this.virtual[this.currentRow][col + 1].isOccupied;
61 | }
62 |
63 | return !isOutofEdge && !isCoverOther;
64 |
65 | } else {
66 | return true;
67 | }
68 |
69 | }
70 | walkVirtualGrid () {
71 | var col = this.currentColumn;
72 | var row = this.currentRow;
73 | var totalCol = this.columns;
74 |
75 | // first check if this one is occupied
76 | while (this.virtual[row][col].isOccupied) {
77 | col++;
78 | if (col >= this.columns) {
79 | col = 0;
80 | row++;
81 | }
82 | // console.log('col:'+col);
83 | // console.log('row:'+row);
84 | }
85 | // check if this item fit in;
86 | while (!this.checkSize(this.currentType, col)) {
87 | this.currentType = Math.ceil(Math.random() * 2) * 2 - 1; // 1, 3
88 |
89 | // console.log('currentType is:'+ this.currentType );
90 | }
91 |
92 | var itemType = this.currentType;
93 |
94 | var startVirtualItem = this.virtual[row][col];
95 |
96 | switch (itemType) {
97 | case 1:
98 | this.virtual[row][col].isOccupied = true;
99 | col++;
100 | break;
101 | case 2:
102 | this.virtual[row][col].isOccupied = true;
103 | this.virtual[row][col + 1].isOccupied = true;
104 | col += 2;
105 | break;
106 | case 3:
107 | this.virtual[row][col].isOccupied = true;
108 | this.virtual[row + 1][col].isOccupied = true;
109 |
110 | col++;
111 | break;
112 | case 4:
113 | this.virtual[row][col].isOccupied = true;
114 | this.virtual[row][col + 1].isOccupied = true;
115 | this.virtual[row + 1][col].isOccupied = true;
116 | this.virtual[row + 1][col + 1].isOccupied = true;
117 |
118 | col += 2;
119 | break;
120 | };
121 |
122 | if (col >= this.columns) {
123 | col = 0;
124 | row++;
125 | }
126 |
127 |
128 | this.currentColumn = col;
129 | this.currentRow = row;
130 |
131 | return startVirtualItem;
132 | }
133 | positionOneItem () {
134 | this.currentType = Math.ceil(Math.random() * 4);
135 |
136 | var virtualItem = this.walkVirtualGrid();
137 |
138 | // console.log(virtualItem);
139 |
140 | return {
141 | top: virtualItem.top,
142 | left: virtualItem.left,
143 | }
144 | }
145 |
146 | fill() {
147 | var self = this;
148 |
149 | this.setUp();
150 |
151 | var itemStyles = [];
152 | for (var ii = 0; ii < this.itemLength; ii++) {
153 | var pos = self.positionOneItem();
154 |
155 | var width, height;
156 | switch (self.currentType) {
157 | case 1:
158 | width = self.baseWidth;
159 | height = self.baseWidth;
160 | break;
161 | case 2:
162 | width = self.baseWidth * 2 + self.gutter;
163 | height = self.baseWidth;
164 | break;
165 | case 3:
166 | width = self.baseWidth;
167 | height = self.baseWidth * 2 + self.gutter;
168 | break;
169 | case 4:
170 | width = self.baseWidth * 2 + self.gutter;
171 | height = self.baseWidth * 2 + self.gutter;
172 | break;
173 | }
174 |
175 | var itemStyle = {
176 | width: width,
177 | height: height,
178 | top: pos.top,
179 | left: pos.left,
180 | };
181 |
182 | itemStyles.push(itemStyle);
183 |
184 | }; // end of for
185 | return itemStyles;
186 | }
187 | refill(){
188 | this.gridWidth = window.innerWidth - 20;
189 | return this.fill();
190 | }
191 | deBouncedRefill(){
192 | return _.debounce( this.refill.bind(this) , 200);
193 | }
194 | }
195 |
196 | module.exports = function(option) {
197 | return new Grid(option);
198 | }
--------------------------------------------------------------------------------
/public/app/stores/navStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var EventEmitter = require('events').EventEmitter;
3 | var navConst = require('../constants/commonConst.js').nav ;
4 | var _ = require('lodash');
5 |
6 | var state = {
7 | isNavOpen: false,
8 | };
9 |
10 | function toggleFunc(openOrCloseOrToggle){
11 | // console.log('__openOrCloseOrToggle:',openOrCloseOrToggle)
12 | if( openOrCloseOrToggle == 'close'){
13 | state.isNavOpen = false;
14 | }else if (openOrCloseOrToggle == 'open'){
15 | state.isNavOpen = true;
16 | }else {
17 | // just toggle
18 | state.isNavOpen = !state.isNavOpen;
19 | }
20 |
21 |
22 | }
23 |
24 | // Extend nav Store with EventEmitter to add eventing capabilities
25 | var navStore = _.extend({}, EventEmitter.prototype, {
26 |
27 | toggle:toggleFunc,
28 |
29 | getState: function(){
30 | return {
31 | isNavOpen: state.isNavOpen
32 | };
33 | },
34 |
35 | // Emit Change event
36 | emitChange: function() {
37 | this.emit('change');
38 | },
39 |
40 | // Add change listener
41 | addChangeListener: function(callback) {
42 | this.on('change', callback);
43 | },
44 |
45 | // Remove change listener
46 | removeChangeListener: function(callback) {
47 | this.removeListener('change', callback);
48 | }
49 |
50 | });
51 |
52 | // Register callback with AppDispatcher
53 | AppDispatcher.register(function(payload) {
54 | var action = payload.action;
55 | var text;
56 |
57 | switch(action.actionType) {
58 |
59 | // Respond to CART_ADD action
60 | case navConst.TOGGLE:
61 | toggleFunc(action.data);
62 | break;
63 |
64 | default:
65 | return true;
66 | }
67 |
68 | // If action was responded to, emit change event
69 | navStore.emitChange();
70 |
71 | return true;
72 |
73 | });
74 |
75 | module.exports = navStore;
76 |
--------------------------------------------------------------------------------
/public/app/stores/projectsStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var EventEmitter = require('events').EventEmitter;
3 | var projectsConst = require('../constants/commonConst.js').projects ;
4 | var _ = require('lodash');
5 |
6 | // bad bad code......bare with me, cause back end is not done yet.......
7 | window.gfShowProjectsGuid = true;
8 |
9 | var state = {
10 | showGuide: window.gfShowProjectsGuid,
11 | };
12 |
13 | function toggleGuide(){
14 | state.showGuide = false;
15 | }
16 |
17 | // Extend nav Store with EventEmitter to add eventing capabilities
18 | var projectsStore = _.extend({}, EventEmitter.prototype, {
19 |
20 | toggleGuide:toggleGuide,
21 |
22 | getState: function(){
23 | return state
24 | },
25 |
26 | // Emit Change event
27 | emitChange: function() {
28 | this.emit('change');
29 | },
30 |
31 | // Add change listener
32 | addChangeListener: function(callback) {
33 | this.on('change', callback);
34 | },
35 |
36 | // Remove change listener
37 | removeChangeListener: function(callback) {
38 | this.removeListener('change', callback);
39 | }
40 |
41 | });
42 |
43 | // Register callback with AppDispatcher
44 | AppDispatcher.register(function(payload) {
45 | var action = payload.action;
46 |
47 | switch( action.actionType ) {
48 |
49 | // Respond to CART_ADD action
50 | case projectsConst.TOGGLEGUIDE:
51 | toggleGuide(action.data);
52 | break;
53 |
54 | default:
55 | return true;
56 | }
57 |
58 | // If action was responded to, emit change event
59 | projectsStore.emitChange();
60 |
61 | return true;
62 |
63 | });
64 |
65 | module.exports = projectsStore;
66 |
--------------------------------------------------------------------------------
/public/app/stores/routeCoverStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var EventEmitter = require('events').EventEmitter;
3 | var routeCoverConst = require('../constants/commonConst.js').routeCover ;
4 | var _ = require('lodash');
5 |
6 | var state = {
7 | isCoverShown: false,
8 | isAnimating: false,
9 | };
10 |
11 | function start(data){
12 | // start animation
13 | state.isCoverShown = true;
14 | }
15 |
16 | function finish(data){
17 | state.isCoverShown = false ;
18 | }
19 |
20 | // Extend nav Store with EventEmitter to add eventing capabilities
21 | var routeCoverStore = _.extend({}, EventEmitter.prototype, {
22 |
23 | getState: function(){
24 | return state
25 | },
26 | setState: function(key,value){
27 | state[key] == value;
28 | },
29 |
30 | // Emit Change event
31 | emitChange: function() {
32 | this.emit('change');
33 | },
34 |
35 | // Add change listener
36 | addChangeListener: function(callback) {
37 | this.on('change', callback);
38 | },
39 |
40 | // Remove change listener
41 | removeChangeListener: function(callback) {
42 | this.removeListener('change', callback);
43 | }
44 |
45 | });
46 |
47 | // Register callback with AppDispatcher
48 | AppDispatcher.register(function(payload) {
49 | var action = payload.action;
50 | var text;
51 |
52 | switch(action.actionType) {
53 |
54 | // Respond to routeCover action
55 | case routeCoverConst.START:
56 | start(action.data);
57 | break;
58 | case routeCoverConst.FINISH:
59 | finish(action.data);
60 | break;
61 |
62 | default:
63 | return true;
64 | }
65 |
66 | // If action was responded to, emit change event
67 | routeCoverStore.emitChange();
68 |
69 | return true;
70 |
71 | });
72 |
73 | module.exports = routeCoverStore;
74 |
--------------------------------------------------------------------------------
/public/data/portfolio.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name":"1th item",
4 | "description":"lorem ipsome delo ca deso someca totl esos cess lorem ipsome delo ca deso someca totl esos cess, lorem ipsome delo ca deso someca totl esos cess",
5 | "url":"item1",
6 | "thumbnail":"images/u1.jpg",
7 | "cover":"images/u1.jpg",
8 | "date":"2015-5-1",
9 | "content":"ss"
10 | },
11 | {
12 | "name":"2th item",
13 | "description":"lorem ipsome delo ca deso someca totl esos cess",
14 | "url":"item2",
15 | "thumbnail":"images/u2.jpg",
16 | "cover":"images/u2.jpg",
17 | "date":"2015-5-1",
18 | "content":"3333 "
19 | },
20 | {
21 | "name":"3th item",
22 | "description":"lorem ipsome delo ca deso someca totl esos cess",
23 | "url":"item3",
24 | "thumbnail":"images/u3.jpg",
25 | "cover":"images/u3.jpg",
26 | "date":"2015-5-1",
27 | "content":"this is some conent "
28 | },
29 | {
30 | "name":"4th item",
31 | "description":"lorem ipsome delo ca deso someca totl esos cess",
32 | "url":"item4",
33 | "thumbnail":"images/u4.jpg",
34 | "cover":"images/u4.jpg",
35 | "date":"2015-5-1",
36 | "content":"this is some conent "
37 | },
38 | {
39 | "name":"5th item",
40 | "description":"lorem ipsome delo ca deso someca totl esos cess",
41 | "url":"item5",
42 | "thumbnail":"images/u5.jpg",
43 | "cover":"images/u5.jpg",
44 | "date":"2015-5-1",
45 | "content":"this is some conent "
46 | },
47 | {
48 | "name":"6th item",
49 | "description":"lorem ipsome delo ca deso someca totl esos cess",
50 | "url":"item6",
51 | "thumbnail":"images/u6.jpg",
52 | "cover":"images/u6.jpg",
53 | "date":"2015-5-1",
54 | "content":"this is some conent "
55 | },
56 | {
57 | "name":"7th item",
58 | "description":"lorem ipsome delo ca deso someca totl esos cess",
59 | "url":"item7",
60 | "thumbnail":"images/u7.jpg",
61 | "cover":"images/u7.jpg",
62 | "date":"2015-5-1",
63 | "content":"this is some conent "
64 | },
65 | {
66 | "name":"8th item",
67 | "description":"lorem ipsome delo ca deso someca totl esos cess",
68 | "url":"item8",
69 | "thumbnail":"images/u8.jpg",
70 | "cover":"images/u8.jpg",
71 | "date":"2015-5-1",
72 | "content":"this is some conent "
73 | },
74 | {
75 | "name":"9th item",
76 | "description":"lorem ipsome delo ca deso someca totl esos cess",
77 | "url":"item9",
78 | "thumbnail":"images/u9.jpg",
79 | "cover":"images/u9.jpg",
80 | "date":"2015-5-1",
81 | "content":"this is some conent "
82 | },
83 | {
84 | "name":"10th item",
85 | "description":"lorem ipsome delo ca deso someca totl esos cess",
86 | "url":"item10",
87 | "thumbnail":"images/u10.jpg",
88 | "cover":"images/u10.jpg",
89 | "date":"2015-5-1",
90 | "content":"this is some conent "
91 | },
92 | {
93 | "name":"11th item",
94 | "description":"lorem ipsome delo ca deso someca totl esos cess",
95 | "url":"item11",
96 | "thumbnail":"images/u11.jpg",
97 | "cover":"images/u11.jpg",
98 | "date":"2015-5-1",
99 | "content":"this is some conent "
100 | },
101 | {
102 | "name":"12th item",
103 | "description":"lorem ipsome delo ca deso someca totl esos cess",
104 | "url":"item12",
105 | "thumbnail":"images/u12.jpg",
106 | "cover":"images/u12.jpg",
107 | "date":"2015-5-1",
108 | "content":"this is some conent "
109 | },
110 | {
111 | "name":"13th item",
112 | "description":"lorem ipsome delo ca deso someca totl esos cess",
113 | "url":"item13",
114 | "thumbnail":"images/u13.jpg",
115 | "cover":"images/u13.jpg",
116 | "date":"2015-5-1",
117 | "content":"this is some conent "
118 | }
119 | ]
--------------------------------------------------------------------------------
/public/data/portfolio/item1.html:
--------------------------------------------------------------------------------
1 |
2 | 半路出家自学搬砖,工头最近管得松,特借此机会录搬砖之法以供分享,鄙人毕业不久水平很菜,还望各路高手手下留情 别把我拍死了。。。。
3 | 教程的几个章节:
4 |
5 | 1.初识ReactJS(讲的太烂,直接跳过吧....)
6 | 2.第一个组件hellow world
7 | 3.组件的嵌套
8 | 4.组件的状态state
9 | 5.组件的参数props
10 | 6.事件events
11 | 7.指向ref
12 | 8.双向数据流
13 | 9.组件生命周期
14 | 10.mixin
15 | 11.1 开发环境和工具
16 | 11.2 分成小组件
17 | 11.3 添加功能
18 | 12.结尾
19 |
20 | 百度网盘 打包下载
21 | 如果大家觉得有用,我讲继续录React+flux+react-router的教程,或许会加上relay,graphQL(如果时间来得及的话)
22 | 教程最后要实现的app:
23 |
24 | 2015年的计划
25 |
--------------------------------------------------------------------------------
/public/data/projects.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "date":"2015-2-1",
4 | "_id":"29423",
5 | "name":"project1",
6 | "description":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco ",
7 | "url":"project1",
8 | "content":"soem",
9 | "cover":"images/u12.jpg"
10 | },{
11 | "date":"2015-3-1",
12 | "_id":"6423",
13 | "name":"project2",
14 | "description":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco ",
15 | "url":"project2",
16 | "content":"here is some content!! well well well, are we going to paridise?
",
17 | "cover":"images/u2.jpg"
18 | },{
19 | "date":"2015-4-1",
20 | "_id":"4243423",
21 | "name":"project3",
22 | "description":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco ",
23 | "url":"project3",
24 | "content":"here is some content!! well well well, are we going to paridise?
",
25 | "cover":"images/u3.jpg"
26 | }
27 | ]
--------------------------------------------------------------------------------
/public/data/projects/project1.html:
--------------------------------------------------------------------------------
1 | this is project 1
2 | and here is some descritpion writen in html
3 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores esse sunt ipsum animi inventore maxime fugiat, voluptas libero ex fuga consectetur eveniet id tenetur, illo recusandae excepturi tempore sint quasi?
--------------------------------------------------------------------------------
/public/data/projects/project2.html:
--------------------------------------------------------------------------------
1 | this is project 2
2 | and here is some descritpion writen in html
3 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores esse sunt ipsum animi inventore maxime fugiat, voluptas libero ex fuga consectetur eveniet id tenetur, illo recusandae excepturi tempore sint quasi?
--------------------------------------------------------------------------------
/public/data/projects/project3.html:
--------------------------------------------------------------------------------
1 | this is project 3
2 | and here is some descritpion writen in html
3 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores esse sunt ipsum animi inventore maxime fugiat, voluptas libero ex fuga consectetur eveniet id tenetur, illo recusandae excepturi tempore sint quasi?
--------------------------------------------------------------------------------
/public/images/u1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u1.jpg
--------------------------------------------------------------------------------
/public/images/u10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u10.jpg
--------------------------------------------------------------------------------
/public/images/u11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u11.jpg
--------------------------------------------------------------------------------
/public/images/u12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u12.jpg
--------------------------------------------------------------------------------
/public/images/u13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u13.jpg
--------------------------------------------------------------------------------
/public/images/u2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u2.jpg
--------------------------------------------------------------------------------
/public/images/u3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u3.jpg
--------------------------------------------------------------------------------
/public/images/u4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u4.jpg
--------------------------------------------------------------------------------
/public/images/u5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u5.jpg
--------------------------------------------------------------------------------
/public/images/u6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u6.jpg
--------------------------------------------------------------------------------
/public/images/u7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u7.jpg
--------------------------------------------------------------------------------
/public/images/u8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u8.jpg
--------------------------------------------------------------------------------
/public/images/u9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/images/u9.jpg
--------------------------------------------------------------------------------
/public/img/cover/contact.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/contact.jpg
--------------------------------------------------------------------------------
/public/img/cover/forest.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/forest.jpg
--------------------------------------------------------------------------------
/public/img/cover/forest2_dim.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/forest2_dim.jpg
--------------------------------------------------------------------------------
/public/img/cover/intro.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/intro.jpg
--------------------------------------------------------------------------------
/public/img/cover/portrait.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/portrait.jpg
--------------------------------------------------------------------------------
/public/img/cover/woods.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/woods.jpg
--------------------------------------------------------------------------------
/public/img/cover/woods_dim.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/cover/woods_dim.jpg
--------------------------------------------------------------------------------
/public/img/d5logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
15 |
16 |
17 |
19 |
21 |
22 |
23 |
25 |
26 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
63 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/public/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/favicon.png
--------------------------------------------------------------------------------
/public/img/icons/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/public/img/icons/arrow-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/public/img/icons/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/public/img/icons/ios7-close-empty.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
11 |
13 |
14 |
--------------------------------------------------------------------------------
/public/img/icons/ios7-close-outline-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
12 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/public/img/icons/ios7-close-outline.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
12 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/public/img/icons/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/img/icons/prev.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/img/page/drag.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 |
--------------------------------------------------------------------------------
/public/img/page/keys.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
--------------------------------------------------------------------------------
/public/img/page/switchmax.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/public/img/page/switchmin.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/public/img/pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/pattern.png
--------------------------------------------------------------------------------
/public/img/social/Sina_Weibo-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/Sina_Weibo-512.png
--------------------------------------------------------------------------------
/public/img/social/be.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/be.png
--------------------------------------------------------------------------------
/public/img/social/facebook-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/facebook-icon.png
--------------------------------------------------------------------------------
/public/img/social/git.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/git.jpg
--------------------------------------------------------------------------------
/public/img/social/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/github.png
--------------------------------------------------------------------------------
/public/img/social/sc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/sc.png
--------------------------------------------------------------------------------
/public/img/social/zhihu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/img/social/zhihu.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 第5维度™工作室 - Eisneim Terry
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/public/lib/modernizr.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.8.3 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function C(a){j.cssText=a}function D(a,b){return C(n.join(a+";")+(b||""))}function E(a,b){return typeof a===b}function F(a,b){return!!~(""+a).indexOf(b)}function G(a,b){for(var d in a){var e=a[d];if(!F(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function H(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:E(f,"function")?f.bind(d||b):f}return!1}function I(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return E(b,"string")||E(b,"undefined")?G(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),H(e,b,c))}function J(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=E(e[d],"function"),E(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),A={}.hasOwnProperty,B;!E(A,"undefined")&&!E(A.call,"undefined")?B=function(a,b){return A.call(a,b)}:B=function(a,b){return b in a&&E(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return I("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!E(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!I("indexedDB",a)},s.hashchange=function(){return z("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return C("background-color:rgba(150,255,150,.5)"),F(j.backgroundColor,"rgba")},s.hsla=function(){return C("background-color:hsla(120,40%,100%,.5)"),F(j.backgroundColor,"rgba")||F(j.backgroundColor,"hsla")},s.multiplebgs=function(){return C("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return I("backgroundSize")},s.borderimage=function(){return I("borderImage")},s.borderradius=function(){return I("borderRadius")},s.boxshadow=function(){return I("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return D("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return I("animationName")},s.csscolumns=function(){return I("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return C((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),F(j.backgroundImage,"gradient")},s.cssreflections=function(){return I("boxReflect")},s.csstransforms=function(){return!!I("transform")},s.csstransforms3d=function(){var a=!!I("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return I("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML=" ",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var K in s)B(s,K)&&(x=K.toLowerCase(),e[x]=s[K](),v.push((e[x]?"":"no-")+x));return e.input||J(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)B(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},C(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.hasEvent=z,e.testProp=function(a){return G([a])},e.testAllProps=I,e.testStyles=y,e.prefixed=function(a,b,c){return b?I(a,b,c):I(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;ffigcaption>a{
40 | cursor: normal;
41 | pointer-events: none;
42 | }
43 | .item-info-wraper{
44 | transition: opacity 1.2s, visibility 0s 1.2s;
45 | visibility: hidden;
46 | opacity: 0;
47 | }
48 | }
49 | }
50 | }
51 | .gf-grid-item{
52 | >figcaption>a{
53 | display: block;
54 | width: 100%;
55 | height: 100%;
56 | position: absolute;
57 | top: 0;
58 | left: 0;
59 | }
60 | .item-info-wraper{
61 | width:100%;
62 | height: 100%;
63 | position: relative;
64 | }
65 | figcaption::before {
66 | position: absolute;
67 | top: 0;
68 | left: 0;
69 | width: 100%;
70 | height: 100%;
71 | background: -webkit-linear-gradient(top, rgba(72,76,97,0) 0%, rgba(72,76,97,0.8) 75%);
72 | background: linear-gradient(to bottom, rgba(72,76,97,0) 0%, rgba(72,76,97,0.8) 75%);
73 | content: '';
74 | opacity: 0;
75 | -webkit-transform: translate3d(0,50%,0);
76 | transform: translate3d(0,50%,0);
77 | }
78 |
79 | h2 {
80 | margin: 0;
81 | position: absolute;
82 | top: 50%;
83 | left: 0;
84 | width: 100%;
85 | font-size: 40px;
86 | font-weight: bold;
87 | // color: #fff;
88 | opacity:0;
89 | -webkit-transition: -webkit-transform 0.35s, opacity 0.35s;
90 | transition: transform 0.35s, opacity 0.35s;
91 | -webkit-transform: translate3d(0,-50%,0);
92 | transform: translate3d(0,-50%,0);
93 | }
94 |
95 | figcaption::before,
96 | p {
97 | -webkit-transition: opacity 0.35s, -webkit-transform 0.35s;
98 | transition: opacity 0.35s, transform 0.35s;
99 | }
100 |
101 | p {
102 | position: absolute;
103 | bottom: 0;
104 | left: 0;
105 | padding: 2em;
106 | width: 100%;
107 | opacity: 0;
108 | -webkit-transform: translate3d(0,10px,0);
109 | transform: translate3d(0,10px,0);
110 | }
111 |
112 | &:hover h2 {
113 | color: #fff;
114 | opacity:1;
115 | -webkit-transform: translate3d(0,-50%,0) translate3d(0,-40px,0);
116 | transform: translate3d(0,-50%,0) translate3d(0,-40px,0);
117 | }
118 |
119 | &:hover figcaption::before ,
120 | &:hover p {
121 | opacity: 1;
122 | -webkit-transform: translate3d(0,0,0);
123 | transform: translate3d(0,0,0);
124 | }
125 | }
126 |
127 | // @keyframes item-morph-in{
128 | // // 0%{
129 | // // width: 100%;
130 | // // height: 100%;
131 | // // }
132 | // 100%{
133 | // top: 0;
134 | // left: 0;
135 | // marg
136 | // width: 100%;
137 | // height: 100%;
138 | // }
139 | // }
--------------------------------------------------------------------------------
/public/scss/component/ideas.scss:
--------------------------------------------------------------------------------
1 | #gf-ideas{
2 |
3 | }
--------------------------------------------------------------------------------
/public/scss/component/intro.scss:
--------------------------------------------------------------------------------
1 | #gf-intro{
2 | background-color: $darker_blue ;
3 | background-image: url('../img/cover/intro.jpg');
4 | background-position: center center;
5 | background-repeat: no-repeat;
6 | background-size: cover;
7 | .gf-centered-wraper{
8 | position:relative;
9 | z-index: 3;
10 | height: 100%;
11 | max-width:800px;
12 | width: 90%;
13 | // float: right;
14 | }
15 | header{
16 | color: #fff;
17 | text-align: left;
18 | font-style: italic;
19 | h1,h2{
20 | text-transform: uppercase;margin:0;
21 | }
22 | h1{
23 | font-size: 6em;
24 | }
25 | h2{
26 | font-size: 5em;
27 | }
28 | h3{
29 | font-size: 3em;
30 | margin: 0;
31 | }
32 | }
33 | #video_background {
34 | position: absolute;
35 | top: 0px;
36 | left: 0px;
37 | min-width: 100%;
38 | min-height: 100%;
39 | width: auto;
40 | height: auto;
41 | // z-index: -1000;
42 | overflow: hidden;
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/public/scss/component/portfolio.scss:
--------------------------------------------------------------------------------
1 | #gf-portfolio{
2 | .portfolio-item{
3 | display: block;
4 | width: 100%;
5 | height: 100%;
6 | margin:0;
7 | padding:0;
8 | background-size: cover;
9 | background-position: center center;
10 | }
11 | &.showItem{
12 | overflow: hidden;
13 | .gf-grid{
14 | // overflow: hidden;
15 | }
16 | .gf-grid .gf-grid-item{
17 |
18 | }
19 | }
20 | .gf-grid{
21 | margin-top: 80px;
22 | padding-bottom: 50px;
23 | }
24 | }
25 | #gf-portfolio-header{
26 | padding: 40px 120px 20px 200px;
27 | }
28 | #gf-portfolio-item{
29 | width:0;
30 | position: absolute;
31 | top:0;
32 | left: 0;
33 | visibility: hidden;
34 | opacity: 0;
35 | &.show{
36 | z-index: 11;
37 | visibility:visible;
38 | width: 100%;
39 | height: 100%;
40 | overflow-y:auto;
41 | opacity: 1;
42 | transition: visibility 0s 0.8s,opacity 0.4s 0.8s;
43 | }
44 | &>.close-btn{
45 | position: fixed;
46 | top: 30px;
47 | right: 120px;
48 | }
49 | .gf-portfolio-item-wrap{
50 | background-color: #efefef;
51 | }
52 | header{
53 | background-size: cover;
54 | background-repeat: no-repeat;
55 | background-position: center center;
56 | // background-attachment: fixed;
57 | margin:0;
58 | padding:0;
59 | }
60 | .portfolio-content{
61 | background-color: #efefef;
62 | color: #666;
63 | font-size: 20px;
64 | h1{font-size:2.5em;}
65 | h2{font-size:2.1em;}
66 | h3{font-size:1.8em;}
67 | h4{font-size:1.5em;}
68 | h5{font-size:1.2em;}
69 | img{
70 | max-width: 100%;
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/public/scss/component/project.scss:
--------------------------------------------------------------------------------
1 | #gf-project{
2 | width:100%;
3 | height:100%;
4 | position:absolute;
5 | top:0;
6 | overflow-y:auto;
7 | padding-top: 100px;
8 | font-size: 20px;
9 | opacity:0;
10 | transition: opacity 0.8s ease-out;
11 | // >.container{
12 | // // opacity:0;
13 |
14 | // }
15 |
16 | h1{font-size:2.5em;}
17 | h2{font-size:2.1em;}
18 | h3{font-size:1.8em;}
19 | h4{font-size:1.5em;}
20 | h5{font-size:1.2em;}
21 | img{
22 | max-width: 100%;
23 | }
24 | &>.close-btn{
25 | position: fixed;
26 | top: 30px;
27 | right: 120px;
28 | }
29 | a{
30 | color: #eee;
31 | font-weight: bold;
32 | &:hover{
33 | color: map-get($color-green,'400');
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/public/scss/component/projects.scss:
--------------------------------------------------------------------------------
1 | #gf-main>section#gf-projects{
2 | overflow-y:hidden;
3 | }
4 | #gf-projects{
5 | transform-style: preserve-3d;
6 | perspective: 1200px;
7 | overflow:hidden;
8 | &.gf-showall{
9 | #gf-projects-drag{
10 | // transform: translate3d(0,0,-100em);
11 | // transform: translate3d(-50%,-50%,0);
12 | width:50%;
13 | height:50%;
14 | // top:25%;
15 | // left:25%;
16 | }
17 | #gf-projects-wraper{
18 | // transform: translate3d(0,0,-100em);
19 | box-shadow: 0 0 50px rgba(0,0,0,0.2);
20 | }
21 | .gf-project-holder:not(.active){
22 | opacity:0.4;
23 |
24 | }
25 | .gf-project-holder{
26 | .gf-project-info{
27 | opacity:0;
28 | transition: opacity 0.3s ease;
29 | }
30 | }
31 | .gf-project-holder.active{
32 | .gf-project-title{
33 | opacity:1;
34 | transform: translateY(0);
35 | }
36 | }
37 |
38 | }// end of gf-showall
39 | // &.gf-showall.gf-leave{
40 | // #gf-projects-drag{
41 |
42 | // }
43 | // }
44 | &.gf-leave, &.gf-showall.gf-leave{
45 | #gf-projects-drag-wrap{
46 | transition: transform 0.5s ease-in,
47 | visibility 0s 0.9s;
48 |
49 | transform: translate3d(0,-105%,0);
50 | visibility: hidden;
51 | }
52 | #gf-projects-switch{
53 | display:none;
54 | }
55 | }
56 |
57 | }
58 |
59 | #guide-overlay{
60 | .info {
61 | text-align: center;
62 | position: absolute;
63 | top: 50%;
64 | left: 0;
65 | -webkit-transform: translateY(-50%);
66 | transform: translateY(-50%);
67 | text-transform: uppercase;
68 | font-weight: 700;
69 | letter-spacing: 1px;
70 | font-size: 80%;
71 | width: 100%;
72 | span {
73 | display: inline-block;
74 | width: 180px;
75 | height: 180px;
76 | padding: 10px;
77 | margin: 4px;
78 | text-align: center;
79 | vertical-align: top;
80 | background-size: 75%;
81 | background-color: rgba(52,73,94,0.7);
82 | background-repeat: no-repeat;
83 | background-position: 50% 85%;
84 | }
85 | }
86 |
87 | .info span.info-drag {
88 | background-image: url(../img/page/drag.svg);
89 | }
90 |
91 | .info span.info-keys {
92 | background-image: url(../img/page/keys.svg);
93 | }
94 |
95 | .info span.info-switch {
96 | background-image: url(../img/page/switchmin.svg);
97 | background-size: 65%;
98 | }
99 | .btn{
100 | margin-top: 1em;
101 | font-size: 2.5em;
102 | }
103 | }
104 |
105 | #gf-projects-drag-wrap{
106 | height: 100%;
107 | width:100%;
108 | position:relative;
109 | transition: transform 0.5s cubic-bezier(0,0,0.01,1.32),
110 | visibility 0s 0s;
111 |
112 | }
113 | #gf-projects-drag{
114 | height: 100%;
115 | width:100%;
116 | position:absolute;
117 | top: 50%;
118 | left:50%;
119 | transform: translate3d(-50%,-50%,0);
120 | transform-origin: 0 0;
121 | cursor: grab;
122 | user-select:none;
123 | // transition: all 0.3s ease-out;
124 | transition: transform 0.3s ease-out,
125 | width 0.3s ease-out,
126 | height 0.3s ease-out;
127 | }
128 | #gf-projects-wraper{
129 | position:absolute;
130 | top: 0;
131 | left: 0;
132 | height: 100%;
133 | // transition: transform 0.3s ease-out;
134 | }
135 | #gf-projects-switch{
136 | // font-size: 20px;
137 | display:block;
138 | position:absolute;
139 | top: 2em;
140 | right: 10em;
141 | z-index: 10;
142 | width: 100px;
143 | height: 100px;
144 | cursor: pointer;
145 | background: url('../img/page/switchmin.svg') center center no-repeat;
146 | .gf-showall & {
147 | background: url('../img/page/switchmax.svg') center center no-repeat;
148 | }
149 | }
150 | .gf-project-holder{
151 | position:relative;
152 | float: left;
153 | height: 100%;
154 | background-image: url('../images/1.jpg');
155 | background-size: cover;
156 | transition: opacity 0.3s;
157 | &:not(.active){
158 |
159 | }
160 | &::before{
161 | content:'';
162 | position:absolute;
163 | display: block;
164 | width: 100%;
165 | height: 100px;
166 | top:0;
167 | left:0;
168 | background-image: linear-gradient(to top,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.09),rgba(0, 0, 0, 0.2) );
169 |
170 | }
171 | .gf-project-title{
172 | text-align: center;
173 | position:absolute;
174 | bottom:-130px;
175 | width:100%;
176 | opacity: 0;
177 | transform: translateY(80px);
178 | transition: opacity 0.3s ease-out, transform 0.3s ease-out;
179 | // h1{margin: 0;}
180 | &>a{
181 | display:block;
182 | margin:0px auto;
183 | width: 60px;
184 | height: 60px;
185 | background: url('../img/icons/arrow-down.svg') center center no-repeat;
186 | animation:sway-up-down 1s ease-in-out infinite alternate;
187 | transform: rotate(-90deg);
188 | }
189 | }
190 | }
191 | .gf-project-info{
192 | position:absolute;
193 | width: 100%;
194 | min-height: 100px;
195 | bottom: 0;
196 | padding: 1em 3em;
197 | background-image: linear-gradient(to bottom,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.6) );
198 | transition: opacity 0.3s 0.3s ease;
199 | // font-style: italic;
200 | h1{
201 | font-size: 60px;
202 | margin-bottom: 10px;
203 | a{
204 | color: map-get($color-cyan,'200');
205 | &:hover{
206 | color: map-get($color-indigo,'400');
207 | }
208 | }
209 | }
210 | p{
211 | font-size: 20px;
212 | }
213 | // text-align: center;
214 | }
--------------------------------------------------------------------------------
/public/scss/layout.scss:
--------------------------------------------------------------------------------
1 | $dark-grey-blue:#2A2E39;
2 |
3 | // put some global class here ------
4 | body,html{
5 | font-family: Lato,Helvetica Neue,"Hiragino Sans GB","Microsoft YaHei","微软雅黑","STHeiti","WenQuanYi Micro Hei",SimSun,sans-serif,Arial;
6 | width: 100%;
7 | height: 100%;
8 | overflow: hidden;
9 | }
10 | h1,h2,h3,h4,h5,*{
11 | // really thin
12 | font-weight: 200;
13 | }
14 | ::selection {
15 | // background: #44FFB4;
16 | background-color: map-get($color-green,'300');
17 | color: #fff;
18 | text-shadow: 0 1px 0 rgba(0,0,0,0.3);
19 | }
20 |
21 |
22 | // =---------------------------------- nav and logo -------------
23 | #gf-app{
24 | width:100%;
25 | height:100%;
26 | }
27 | #gf-main{
28 | width:100%;
29 | height: 100%;
30 | overflow:hidden;
31 | background-color: $dark-grey-blue;//$darker_blue;
32 | color: #fff;
33 |
34 | transition: margin-left 0.3s ease-out;
35 | &>section, &>.gf-view{
36 | width: 100%;
37 | height:100%;
38 | overflow-y: auto;
39 | animation:fade-in 1s ease-out;
40 | animation-fill-mode: forwards;
41 | // clearfix
42 | &:before,
43 | &:after {
44 | content: " "; /* 1 */
45 | display: table; /* 2 */
46 | }
47 | &:after {
48 | clear: both;
49 | }
50 |
51 | }
52 | }
53 | #gf-logo{
54 | z-index: $index-logo;
55 | position: absolute;
56 | top: 2em;
57 | left: 2em;
58 | width: 200px;
59 | user-select:none;
60 | }
61 | #gf-nav-toggle{
62 | // position: static;
63 | position: absolute;
64 | z-index: $index-nav-toggle;
65 | top: 1em;
66 | right: 1.5em;
67 | }
68 | #gf-nav{
69 | position: absolute;
70 | right:-305px;
71 | top: 0;
72 | height: 100%;
73 | width: 300px;
74 | // background-color: map-get($color-teal,'500');
75 | background-color: #fff;
76 | // background-color:$blue_grey;
77 | // color: #fff;
78 | // box-shadow: -2px 0 6px rgba(0,0,0,0.1);
79 | z-index: $index-nav;
80 |
81 | transition: right 0.3s ease;
82 | #nav-svg-wrap{
83 | pointer-events:none;
84 | }
85 | #gf-nav-main-link{
86 | font-size: 2em;
87 | padding: 1em;
88 | li{
89 | margin-bottom: 0.2em;
90 | }
91 | }
92 |
93 | }
94 | #gf-nav-backdrop{
95 | position: absolute;
96 | left: 0;
97 | top: 0;
98 | height: 100%;
99 | width: 100%;
100 | visibility:hidden;
101 | background-color: rgba(0,0,0,0.3);
102 | z-index: 100;
103 | cursor: e-resize;
104 | }
105 | #gf-nav-bottom{
106 | text-align: center;
107 | position:absolute;
108 | bottom:0;
109 | z-index: 5;
110 | color: #999;
111 | }
112 | #gf-nav-social-link{
113 | width: 100%;
114 | // text-align: center;
115 | li{
116 | display: inline-block;
117 | }
118 | }
119 | // --------------- side nav open and close ----
120 | #gf-app.show-nav{
121 | #gf-nav{
122 | right:0;
123 | }
124 | #gf-main{
125 | margin-left: -100px;
126 | }
127 | #gf-nav-backdrop{
128 | visibility:visible
129 | }
130 | #gf-nav-bottom{
131 | left:-60px;
132 | }
133 | }
134 | // ------------------ nav triangle svg
135 | #nav-svg-wrap{
136 | position: absolute;
137 | top: 0;
138 | left:-198px;
139 | width:200px;
140 | height:100%;
141 | // background:red;
142 | }
143 |
144 | // --------------- route cover
145 | #gf-route-cover{
146 | width:100%;
147 | height: 100%;
148 | position:absolute;
149 | top: 0;
150 | left:0;
151 | z-index: 99;
152 | display: none;
153 | }
--------------------------------------------------------------------------------
/public/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import '_var.scss';
2 | @import '_color_palette.scss';
3 | @import '_mixins.scss';
4 | @import 'reset.scss';
5 | @import 'layout.scss';
6 | @import 'animation.scss';
7 |
8 |
9 | @import 'common_style.scss';
10 | @import 'buttons.scss';
11 | @import 'plugins.scss';
12 |
13 | @import 'component/form.scss';
14 | @import 'component/intro.scss';
15 | @import 'component/about.scss';
16 | @import 'component/portfolio.scss';
17 | @import 'component/grid.scss';
18 | @import 'component/projects.scss';
19 | @import 'component/project.scss';
20 | @import 'component/ideas.scss';
21 | @import 'component/blog.scss';
22 | @import 'component/contact.scss';
--------------------------------------------------------------------------------
/public/scss/plugins.scss:
--------------------------------------------------------------------------------
1 | .dragdealer {
2 | position: relative;
3 | height: 30px;
4 | }
5 | .dragdealer .handle {
6 | position: absolute;
7 | top: 0;
8 | left: 0;
9 | }
10 | .dragdealer .red-bar {
11 | width: 100px;
12 | height: 30px;
13 | background: #CC0000;
14 | color: #FFF;
15 | font-size: 14px;
16 | line-height: 30px;
17 | text-align: center;
18 | }
19 | .dragdealer .disabled {
20 | background: #898989;
21 | }
22 | // ------------------
--------------------------------------------------------------------------------
/public/scss/reset.scss:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 | *, *:before, *:after {
6 | -webkit-box-sizing: border-box;
7 | -moz-box-sizing: border-box;
8 | box-sizing: border-box;
9 | }
10 |
11 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}
12 | h1,h2,h3,h4,h5{font-weight: normal;}
13 | // --------------------------
14 | .clearfix {
15 | &:before,
16 | &:after {
17 | content: " "; /* 1 */
18 | display: table; /* 2 */
19 | }
20 | &:after {
21 | clear: both;
22 | }
23 | }
24 | .center {
25 | display: block;
26 | margin-left: auto;
27 | margin-right: auto;
28 | }
29 | .pull-right {
30 | float: right !important;
31 | }
32 | .pull-left {
33 | float: left !important;
34 | }
35 | .text-left{text-align: left !important;}
36 | .text-center{text-align: center !important;}
37 | .text-right{text-align: right !important;}
38 | // ------------------------
39 | // ------------flex box---------
40 | .flex-conainer{
41 | display: flex;
42 | &.flex-row{
43 | flex-direction: row;
44 | }
45 | &.flex-column{
46 | flex-direction: column;
47 | }
48 | }
49 | .flex{
50 | // flex:1 1 auto;
51 | // flex-grow:auto;
52 | flex:1;
53 | // 用下面参数指定自己的位置
54 | // align-self: auto | flex-start | flex-end | center | baseline | stretch;
55 | }
56 | // older version, what i used before, put it here 以防万一
57 | .grid {
58 | /* As of August 2012, only supported in Chrome 21+ */
59 | display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
60 | display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
61 | display: -ms-flexbox; /* TWEENER - IE 10 */
62 | display: -webkit-flex;
63 | display: flex;
64 | min-height: 200px;
65 | }
66 | .fluid {
67 | -webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
68 | -moz-box-flex: 1; /* OLD - Firefox 19- */
69 | -webkit-flex: 1; /* Chrome */
70 | -ms-flex: 1;
71 | flex: 1;
72 | }
73 | // -----------------
74 | // -======================================= center an div =============
75 | /* This parent can be any width and height */
76 | .ua-centered-wraper {
77 | text-align: center;
78 | }
79 | /* The ghost, nudged to maintain perfect centering */
80 | .ua-centered-wraper:before {
81 | content: '';
82 | display: inline-block;
83 | height: 100%;
84 | vertical-align: middle;
85 | margin-right: -0.25em; /* Adjusts for spacing */
86 | }
87 |
88 | /* The element to be centered, can
89 | also be of any width and height */
90 | .ua-centered {
91 | display: inline-block;
92 | vertical-align: middle;
93 | max-width: 95%;
94 | }
95 |
--------------------------------------------------------------------------------
/public/video/splash.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/video/splash.mp4
--------------------------------------------------------------------------------
/public/video/splash.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/public/video/splash.webm
--------------------------------------------------------------------------------
/server.go:
--------------------------------------------------------------------------------
1 | /*!
2 | * gortfolio v0.0.1
3 | * http://eisneim.github.io/gortfolio
4 | *
5 | * the goal is to create an awesome & easy to use portfolio CMS for
6 | * Designers / Artists / Developers
7 | * using: golang as backend , React.JS as frontend MV* framework , mongodb as database
8 | *
9 | * Copyright (c) 2015 eisneim.com
10 | * License: MIT
11 | */
12 |
13 | package main
14 |
15 | import (
16 | "flag"
17 | "github.com/eisneim/gortfolio/gortfolio"
18 | )
19 |
20 | func main() {
21 | // command line flags, flag Prase() returnd with pointers
22 | port := flag.Int("port", 8000, "port to serve on")
23 | dir := flag.String("dir", "public/", "directory of static files ")
24 | flag.Parse()
25 |
26 | gortfolio.Serve(*port, *dir)
27 | }
28 |
--------------------------------------------------------------------------------
/server/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | // "html/template"
7 | // "io/ioutil"
8 | "log"
9 | "os"
10 | // "path/filepath"
11 | "runtime"
12 | )
13 |
14 | type ConfigStruct struct {
15 | Host string `json:"host"`
16 | Port int `json:"port"`
17 | DB string `json:"db"`
18 | GithubClientId string `json:"github_auth_client_id"`
19 | GithubClientSecret string `json:"github_auth_client_secret"`
20 | GithubLoginRedirect string `json:"github_login_redirect"`
21 | GithubLoginSuccessRedirect string `json:"github_login_success_redirect"`
22 | GoVersion string
23 | RootPath string
24 | }
25 |
26 | var Config ConfigStruct
27 |
28 | func Register() ConfigStruct {
29 | // get he root path of our application
30 | rootDir, err := os.Getwd() //filepath.Abs(filepath.Dir(os.Args[0]))
31 | if err != nil {
32 | log.Fatal(err)
33 | }
34 | fmt.Println(rootDir)
35 |
36 | file, err := os.Open(rootDir + "/app_config.json")
37 | if err != nil {
38 | log.Fatal("配置文件读取失败:", err.Error())
39 | }
40 | defer file.Close()
41 |
42 | dec := json.NewDecoder(file)
43 | err = dec.Decode(&Config)
44 | if err != nil {
45 | log.Fatal("配置文件解析失败: ", err.Error())
46 | }
47 |
48 | Config.GoVersion = runtime.Version()
49 | Config.RootPath = rootDir
50 |
51 | return Config
52 | }
53 |
54 | func GetConfig() ConfigStruct {
55 | if Config.GoVersion != "" {
56 | return Config
57 | } else {
58 | return Register()
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/server/config/config_test.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestConfigVars(t *testing.T) {
8 | config := GetConfig()
9 | if config.Host != "localhost" {
10 | t.Errorf("shold read app_config.json file")
11 | }
12 |
13 | if Config.Port != 8888 {
14 | t.Errorf("should readConf directly %s", "!")
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/server/config/db.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "gopkg.in/mgo.v2"
5 | )
6 |
7 | func GetDB() (*mgo.Database, *mgo.Session) {
8 | /*
9 | SessionDB, err := mgo.Dial("localhost")
10 | if err != nil {
11 | panic(err)
12 | }
13 | defer SessionDB.Close()
14 |
15 | Optional. Switch the SessionDB to a monotonic behavior.
16 | SessionDB.SetMode(mgo.Monotonic, true)
17 |
18 | DB = SessionDB.DB("gortfolio")
19 | ColUser = DB.C("users")
20 | */
21 | config := GetConfig()
22 |
23 | session, err := mgo.Dial(config.Host)
24 | if err != nil {
25 | panic(err.Error())
26 | }
27 | database := session.DB(config.DB)
28 | return database, session
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/server/controllers/ctrl.sys.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "net/http"
6 | // "github.com/eisneim/gortfolio/server/config"
7 | )
8 |
9 | /**
10 | * return the install form
11 | * @param {[type]} c *gin.Context [description]
12 | */
13 | func Sys_getInstall(c *gin.Context) {
14 | c.HTML(http.StatusOK, "install.html", nil)
15 | }
16 |
17 | func Sys_install(c *gin.Context) {
18 | c.String(http.StatusOK, "should do the installation ==> ")
19 | }
20 |
--------------------------------------------------------------------------------
/server/controllers/ctrl.user.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "net/http"
6 | // "github.com/eisneim/gortfolio/server/config"
7 | )
8 |
9 | func User_new(c *gin.Context) {
10 | c.String(http.StatusOK, "should create a new User here")
11 | }
12 |
13 | func User_get(c *gin.Context) {
14 | c.String(http.StatusOK, "should get a User "+c.Params.ByName("userId"))
15 | }
16 |
17 | func User_update(c *gin.Context) {
18 | c.String(http.StatusOK, "should update a User "+c.Params.ByName("userId"))
19 | }
20 |
21 | func User_delete(c *gin.Context) {
22 | c.String(http.StatusOK, "should elte User here"+c.Params.ByName("userId"))
23 | }
24 |
--------------------------------------------------------------------------------
/server/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/eisneim/gortfolio/server/config"
6 | "github.com/eisneim/gortfolio/server/routes"
7 | "github.com/gin-gonic/contrib/static"
8 | "github.com/gin-gonic/gin"
9 | )
10 |
11 | func main() {
12 | appConfig := config.GetConfig()
13 |
14 | r := gin.Default()
15 | /**
16 | * load in all html the templates
17 | */
18 | r.LoadHTMLGlob(appConfig.RootPath + "/server/views/*")
19 | /**
20 | * register all the route handlers
21 | */
22 | routes.RegisterRoutes(r)
23 | /**
24 | * serve static files
25 | * r.Static("/s", appConfig.RootPath+"/public")
26 | */
27 | r.Use(static.Serve("/", static.LocalFile(appConfig.RootPath+"/public", false)))
28 |
29 | // Listen and server on 0.0.0.0:8080
30 | r.Run(fmt.Sprintf(":%d", appConfig.Port))
31 | }
32 |
--------------------------------------------------------------------------------
/server/models/model.media.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Media struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Type string `bson:"type"` // image, audio, video
14 | Src string `bson:"src"`
15 | Name string `bson:"name"`
16 | Size string `bson:"size"`
17 | Author bson.ObjectId `bson:"author"`
18 | ProjectIDs []bson.ObjectId `bson:"projectIDs"`
19 | PortfolioIDs []bson.ObjectId `bson:"portfolioIDs"`
20 | }
21 |
22 | func init() {
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/server/models/model.portfolio.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Portfolio struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | PortfolioType string `bson:"type"` // video, iilustration, design, paint,
14 | Medias []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Description string `bson:"Description"`
17 | Viewed int `bson:"viewed"`
18 | Voted int `bson:"voted"`
19 | Cards []PortfolioCard `bson:"cards"`
20 | }
21 |
22 | type PortfolioCard struct {
23 | Media bson.ObjectId `bson:"media"`
24 | Type string `bson:"type"` // image, audio, video
25 | Src string `bson:"src"`
26 | Description string `bson:"description"`
27 | }
28 |
29 | func init() {
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/server/models/model.project.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Project struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Author bson.ObjectId `bson:"author"`
14 | MediaIDs []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Cover bson.ObjectId `bson:"cover"`
17 | Description string `bson:"description"`
18 | ViewCount int `bson:"viewed"`
19 | VoteCount int `bson:"voted"`
20 | Cards []projectCard `bson:"cards"`
21 | Detail string `bson:"detail"`
22 | }
23 |
24 | type projectCard struct {
25 | Media bson.ObjectId `bson:"media"`
26 | Type string `bson:"type"` // image, audio, video
27 | Src string `bson:"src"`
28 | Description string `bson:"description"`
29 | }
30 |
31 | func init() {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/server/models/model.sys.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type Sys struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Author bson.ObjectId `bson:"author"`
14 | Medias []bson.ObjectId `bson:"medias"`
15 | Name string `bson:"name"`
16 | Description string `bson:"Description"`
17 | Viewed int `bson:"viewed"`
18 | Voted int `bson:"voted"`
19 | Cards []SysCard `bson:"cards"`
20 | }
21 |
22 | type SysCard struct {
23 | Media bson.ObjectId `bson:"media"`
24 | Type string `bson:"type"` // image, audio, video
25 | Src string `bson:"src"`
26 | Description string `bson:"description"`
27 | }
28 |
29 | func init() {
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/server/models/model.user.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | // "encoding/json"
5 | // "gopkg.in/mgo.v2"
6 | "gopkg.in/mgo.v2/bson"
7 | // "log"
8 | // "net/http"
9 | )
10 |
11 | type User struct {
12 | Id bson.ObjectId `bson:"_id,omitempty"`
13 | Username string `bson:"username"`
14 | Email string `bson:"email"`
15 | Avatar string `bson:"avatar"`
16 | Security userSecurity `bson:"security"`
17 | Posts []bson.ObjectId `bson:"posts"`
18 | }
19 | type userSecurity struct {
20 | Salt string `bson:"salt"`
21 | Hash string `bson:"hash"`
22 | }
23 |
24 | // type userPosts [ bson.ObjectId ]
25 |
26 | func init() {
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/server/routes/routes.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import (
4 | "github.com/eisneim/gortfolio/server/controllers"
5 | "github.com/gin-gonic/gin"
6 | "net/http"
7 | )
8 |
9 | func RegisterRoutes(r *gin.Engine) {
10 |
11 | r.GET("/", func(c *gin.Context) {
12 | // c.String(http.StatusOK, "this is our home page")
13 | c.HTML(http.StatusOK, "index.html", nil)
14 |
15 | })
16 |
17 | // --------------------------- user apis ---------------
18 |
19 | r.POST("/v1/users", controllers.User_new)
20 |
21 | r.GET("/v1/users/:userId", controllers.User_get)
22 |
23 | r.PUT("/v1/users/:userId", controllers.User_update)
24 |
25 | r.DELETE("/v1/users/:userId", controllers.User_delete)
26 |
27 | // --------------------------- system apis ---------------
28 |
29 | r.GET("/sys/install", controllers.Sys_getInstall)
30 |
31 | r.POST("/sys/install", controllers.Sys_install)
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/server/utils/dateTime.go:
--------------------------------------------------------------------------------
1 | /**
2 | * date and time parsing utils
3 | */
4 | package utils
5 |
6 | import ()
7 |
8 | func parseTime() {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/server/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 第5维度™工作室 - Eisneim Terry
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/server/views/install.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | gortfolio installation
14 |
15 |
16 |
17 |
18 |
19 | Site Name
20 |
21 |
22 | User Name
23 |
24 |
25 | Email
26 |
27 |
28 | Password
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eisneim/gortfolio/83842f2f21b246623cee6a373abd78dfcadc7ed6/snapshot.png
--------------------------------------------------------------------------------
/test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | )
7 |
8 | type somestring struct {
9 | Host string
10 | }
11 |
12 | func main() {
13 | var aa somestring
14 |
15 | fmt.Println(reflect.TypeOf(a))
16 |
17 | if aa.Host == "" {
18 | fmt.Println("it is empty ")
19 | } else {
20 | fmt.Println("it is not empty")
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------