├── .gitignore ├── README.md ├── css ├── interval.md ├── iphone_scroll.css ├── library │ ├── align.scss │ ├── display.scss │ ├── reorder.scss │ └── space.scss ├── mixin.scss ├── offset_right.scss ├── rated_star.scss ├── setting.scss ├── svg_ssetting.scss └── tool.scss ├── git └── git.md ├── html └── fontawesome.html ├── jquery ├── ajax.md ├── get_url_path.js └── image_show_immediate.md ├── js ├── audio_play_bar.html.erb ├── blob.js ├── clear_hover.md ├── css_block_debug.md ├── get_view_height_width.js ├── like_super.js ├── search_input_timer.js ├── timer.js └── watch.js ├── rails ├── asset_boost_track.rb ├── cache_asset_pipline_known.rb ├── parperclip_defalut_img_setting.rb └── precomplie_setting.rb ├── rspec └── rspec.md ├── ruby ├── http_code_render_and_serialize.rb └── plan_model.rb ├── server ├── azure_face_detection.md ├── elasticsearch.md ├── elk_config_settings.md ├── encrypt_like_pem.md └── nginx_site_enable_yml.md └── sql ├── remote_to_server_database.md └── set_character.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 此處是我的人生小筆記 2 | 不記下來全部忘光光 3 | 4 | * 用心好文專區 5 | * [You are not a Sidekiq professional if you don’t know these tricks](https://medium.com/@et3216/9-ways-to-boost-sidekiq-performance-correctly-in-practical-experiences-bfebe9ee0f28) 6 | * [嚇死你的RubyMine怎麼帶我向上飛 分享它如何解省我的時間升生產力](https://medium.com/@et3216/rubymine-%E5%B8%B6%E6%88%91%E5%90%91%E4%B8%8A%E9%A3%9B-8478c30af49c#.909qxa3cc) 7 | * [私人手工製作的Library 內含可彈性的控制RWD的Library、大量省Code的觀念](https://github.com/lustan3216/Behavior-Bind-Media) 8 | 9 | * CSS 10 | * [CSS 文字溢出](https://github.com/lustan3216/BlogArticle/wiki/CSS-%E6%96%87%E5%AD%97%E6%BA%A2%E5%87%BA) 11 | * [RWD replace pull push trick](https://github.com/lustan3216/BlogArticle/wiki/RWD-replace-pull-push-trick) 12 | * [Display rated star by Font Awesome Scss](https://github.com/lustan3216/BlogArticle/wiki/Display-rated-star-by-Font-Awesome-scss) 13 | * [Create Svg Icon](https://github.com/lustan3216/BlogArticle/wiki/Create-Svg-Icon) 14 | 15 | * Rails 16 | * [Parperclip default_url 的設定](https://github.com/lustan3216/BlogArticle/wiki/Parperclip-default-_url-%E7%9A%84%E8%A8%AD%E5%AE%9A) 17 | * [DCI 學習小祕技](https://github.com/lustan3216/BlogArticle/wiki/DCI-%E5%AD%B8%E7%BF%92%E5%B0%8F%E7%A5%95%E6%8A%80) 18 | * [Searchkick Elastic search 使用祕技](https://github.com/lustan3216/BlogArticle/wiki/Searchkick-Elastic-search-%E4%BD%BF%E7%94%A8%E7%A5%95%E6%8A%80) 19 | * [Rails 怎麼切割 mobile/computer view 技巧](https://github.com/lustan3216/BlogArticle/wiki/Rails-%E6%80%8E%E9%BA%BC%E5%88%87%E5%89%B2-mobile-computer-view-%E6%8A%80%E5%B7%A7) 20 | * [本地precompiler 優化](https://github.com/lustan3216/BlogArticle/blob/master/rails/precomplie_setting.rb) 21 | * [指定JS、CSS只在需要的頁面作用技巧](https://github.com/lustan3216/BlogArticle/blob/master/rails/asset_boost_track.rb) 22 | 23 | * Ruby 24 | * [Ruby 讀書心得整理](https://github.com/lustan3216/BlogArticle/wiki/Ruby-%E8%AE%80%E6%9B%B8%E5%BF%83%E5%BE%97%E6%95%B4%E7%90%86) 25 | * [Parperclip exif wrong orientation from mobile upload](https://github.com/lustan3216/BlogArticle/wiki/Parperclip-exif-wrong-orientation-from-mobile-upload) 26 | * [超輕量化Rails model](https://github.com/lustan3216/BlogArticle/blob/master/ruby/plan_model.rb) 27 | * [Http code json render](https://github.com/lustan3216/BlogArticle/blob/master/ruby/http_code_render_and_serialize.rb) 28 | 29 | * SQL 30 | * [Mysql 匯出匯入資料用法](https://github.com/lustan3216/BlogArticle/wiki/Mysql--%E5%8C%AF%E5%87%BA%E5%8C%AF%E5%85%A5%E8%B3%87%E6%96%99%E7%94%A8%E6%B3%95) 31 | * [SQL SHELL.SCIPT語法 讓所有table新增欄位和更新欄位](https://github.com/lustan3216/BlogArticle/wiki/SQL-SHELL.SCIPT%E8%AA%9E%E6%B3%95-%E8%AE%93%E6%89%80%E6%9C%89table%E6%96%B0%E5%A2%9E%E6%AC%84%E4%BD%8D%E5%92%8C%E6%9B%B4%E6%96%B0%E6%AC%84%E4%BD%8D) 32 | 33 | * Server 34 | * [設定SSL Https & HSTS](https://github.com/lustan3216/BlogArticle/wiki/%E8%A8%AD%E5%AE%9ASSL-Https-&-HSTS) 35 | * [Nginx site-enable yml 設定](https://github.com/lustan3216/BlogArticle/blob/master/server/nginx_site_enable_yml.md) 36 | * [Azure face-detection Api中文解釋](https://github.com/lustan3216/BlogArticle/wiki/Azure-face-detection-Api%E4%B8%AD%E6%96%87%E8%A7%A3%E9%87%8B) 37 | * [Elasticsearch 一定會撞的坑](https://github.com/lustan3216/BlogArticle/blob/master/server/elasticsearch.md) 38 | * [ELK 設定檔](https://github.com/lustan3216/BlogArticle/blob/master/server/elk_config_settings.md) 39 | 40 | * JQuery/JS 41 | * [前端好用 套件](https://github.com/lustan3216/BlogArticle/wiki/%E5%89%8D%E7%AB%AF%E5%A5%BD%E7%94%A8-%E5%A5%97%E4%BB%B6) 42 | * [JS偵測 物件出現在 viewprot](https://github.com/lustan3216/BlogArticle/wiki/JS%E5%81%B5%E6%B8%AC--%E7%89%A9%E4%BB%B6%E5%87%BA%E7%8F%BE%E5%9C%A8-viewprot) 43 | * [3D Banner animate](https://github.com/lustan3216/BlogArticle/wiki/3D-Banner-animate) 44 | * [Modernizr 範例code](https://github.com/lustan3216/BlogArticle/wiki/Modernizr-%E7%AF%84%E4%BE%8Bcode) 45 | * [Change Svg path color](https://github.com/lustan3216/BlogArticle/wiki/Change-Svg-path-color) 46 | * [Audio play bar full example](https://github.com/lustan3216/BlogArticle/blob/master/js/audio_play_bar.html.erb) 47 | * [clear hover on mobile](https://github.com/lustan3216/BlogArticle/blob/master/js/clear_hover.md) 48 | * [js debug code, its can display block leyout random color](https://github.com/lustan3216/BlogArticle/blob/master/js/css_block_debug.md) 49 | * [search timer and clean/clean all timer](https://github.com/lustan3216/BlogArticle/blob/master/js/search_input_timer.js) 50 | * [Show image when upload](https://github.com/lustan3216/BlogArticle/blob/master/jquery/image_show_immediate.md) 51 | * [Simple Time prototype](https://github.com/lustan3216/BlogArticle/blob/master/js/timer.js) 52 | * [Act like super function](https://github.com/lustan3216/BlogArticle/blob/master/js/like_super.js) 53 | * [Act like watch function](https://github.com/lustan3216/BlogArticle/blob/master/js/watch.js) 54 | 55 | * Commend line 56 | * [Commend有時用到 指令 祕技](https://github.com/lustan3216/BlogArticle/wiki/Commend%E6%9C%89%E6%99%82%E7%94%A8%E5%88%B0-%E6%8C%87%E4%BB%A4-%E7%A5%95%E6%8A%80) 57 | 58 | * 密碼學 59 | * [仿造簡易Pem key步驟](https://github.com/lustan3216/BlogArticle/blob/master/server/encrypt_like_pem.md) 60 | * [BCrypt 加密演算法精闢解釋](https://github.com/lustan3216/BlogArticle/wiki/BCrypt-%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95%E7%B2%BE%E9%97%A2%E8%A7%A3%E9%87%8B) 61 | -------------------------------------------------------------------------------- /css/interval.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | 4 | 5 | ``` -------------------------------------------------------------------------------- /css/iphone_scroll.css: -------------------------------------------------------------------------------- 1 | body{ 2 | -webkit-overflow-scrolling: touch; 3 | } -------------------------------------------------------------------------------- /css/library/align.scss: -------------------------------------------------------------------------------- 1 | @mixin method_loop($media) { 2 | // text-align 3 | @each $direction,$direction_short in (right,'r'),(left,'l'),(center,'c'),(inherit,'n') { 4 | .ta#{$direction_short}-#{$media} { text-align:$direction;} 5 | } 6 | // float 7 | @each $direction,$direction_short in (right,'r'),(left,'l'),(inherit,'n') { 8 | .fl#{$direction_short}-#{$media} { float:$direction; } 9 | } 10 | } 11 | 12 | @include method_loop('xs'); 13 | 14 | @media (min-width: $screen-sm-min) { 15 | @include method_loop('sm'); 16 | } 17 | 18 | @media (min-width: $screen-md-min) { 19 | @include method_loop('md'); 20 | } 21 | 22 | @media (min-width: $screen-lg-min) { 23 | @include method_loop('lg'); 24 | } -------------------------------------------------------------------------------- /css/library/display.scss: -------------------------------------------------------------------------------- 1 | @mixin flex{ 2 | display: -webkit-box; 3 | display: -moz-box; 4 | display: -ms-flexbox; 5 | display: -webkit-flex; 6 | } 7 | 8 | @mixin method_loop($media) { 9 | //display 10 | @each $method,$method_short in (block,'b'),(inline-block,'ib'),(inline,'i'),(inherit,'n') { 11 | .d#{$method_short}-#{$media} { display: $method; } 12 | } 13 | } 14 | @mixin method_loop_f($media) { 15 | //display 16 | .df-#{$media} { @include flex;} 17 | } 18 | @mixin method_loop_f_no_media($media) { 19 | //display 20 | .df-#{$media} { @include flex; } 21 | } 22 | 23 | @include method_loop('xs'); 24 | @include method_loop_f('xs'); 25 | @include method_loop_f_no_media('xs'); 26 | 27 | @media (min-width: $screen-sm-min) { 28 | @include method_loop('sm'); 29 | @include method_loop_f('sm'); 30 | @include method_loop_f_no_media('sm'); 31 | } 32 | 33 | @media (min-width: $screen-md-min) { 34 | @include method_loop('md'); 35 | @include method_loop_f('md'); 36 | @include method_loop_f_no_media('md'); 37 | } 38 | 39 | @media (min-width: $screen-lg-min) { 40 | @include method_loop('lg'); 41 | @include method_loop_f('lg'); 42 | @include method_loop_f_no_media('lg'); 43 | } -------------------------------------------------------------------------------- /css/library/reorder.scss: -------------------------------------------------------------------------------- 1 | .rotate_180{ 2 | -webkit-transform: rotate(180deg); 3 | -moz-transform: rotate(180deg); 4 | -ms-transform: rotate(180deg); 5 | -o-transform: rotate(180deg); 6 | transform: rotate(180deg); 7 | } 8 | 9 | @mixin reverse_column($_){ 10 | .row.reverse-#{$_}{ 11 | @extend .rotate_180; 12 | direction: rtl; 13 | } 14 | 15 | .row.reverse-#{$_} > [class*="col-"]{ 16 | @extend .rotate_180; 17 | direction: ltr; 18 | } 19 | } 20 | @media (max-width: $screen-xs-max) { 21 | @include reverse_column('xs'); 22 | } 23 | @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { 24 | @include reverse_column('sm'); 25 | } 26 | 27 | @media (min-width: $screen-md-min) and (max-width: $screen-md-max) { 28 | @include reverse_column('md'); 29 | } 30 | 31 | @media (min-width: $screen-lg-min) and (max-width: $screen-lg-max) { 32 | @include reverse_column('lg'); 33 | } -------------------------------------------------------------------------------- /css/library/space.scss: -------------------------------------------------------------------------------- 1 | // 用法解釋 *表示數字 數字可以是 0px,10px,15px,20px~~100px 2 | // 以上數字為最常用的數字 要增加自己家在下面 3 | // ------------------------------------------------------- 4 | // xs(320up) | sm(768up) | md(992up) | lg(1200up) 5 | // ------------------------------------------------------- 6 | // mt*-xs Yes | Yes | Yes | Yes 7 | // mt* Yes | Yes | Yes | Yes 8 | // ------------------------------------------------------- 9 | // mt*-sm No | Yes | Yes | Yes 10 | // ------------------------------------------------------- 11 | // mt*-md No | No | Yes | Yes 12 | // ------------------------------------------------------- 13 | // mt*-lg No | No | No | Yes 14 | // ------------------------------------------------------- 15 | // Yes 表示有作用的區域 No表示沒作用的區域 16 | // 17 | // 使用方式 【 直接對該class上 mb20-sm 這樣就只會在sm media以上作用magin-bottom 20px 】 18 | // 【 pl50-md 這樣就只會在md media以上作用padding-left 50px 】 19 | // 20 | // 使用時機 【 該區塊class很難取名 或是整塊區域只有單個元素需變動而不想再取class名字】 21 | // 適用於 【 喜歡 CSS 元件化 的工程師 】 22 | 23 | @mixin method_loop_two_way($media) { 24 | @each $method,$method_short in (margin,'m'),(padding,'p') { 25 | @for $i from 0 through 200 { 26 | @each $direction,$direction2,$direction_short,$direction2_short in (right,left,'r','l'),(top,bottom,'t','b') { 27 | @if $i % 5 == 0 { 28 | .#{$method_short}#{$direction_short}#{$direction2_short}#{$i}-#{$media} { #{$method}-#{$direction}: #{$i}px !important;#{$method}-#{$direction2}: #{$i}px !important; } 29 | @if $media == 'xs'{ 30 | .#{$method_short}#{$direction_short}#{$direction2_short}#{$i} { #{$method}-#{$direction}: #{$i}px !important;#{$method}-#{$direction2}: #{$i}px !important; } 31 | } 32 | @if $i == 0{ 33 | .#{$method_short}#{$direction_short}#{$direction2_short}a-#{$media} { #{$method}-#{$direction}: auto !important;#{$method}-#{$direction2}: auto !important; } 34 | @if $media == 'xs'{ 35 | .#{$method_short}#{$direction_short}#{$direction2_short}a { #{$method}-#{$direction}: auto !important;#{$method}-#{$direction2}: auto !important; } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | @mixin method_loop_full($media) { 44 | @each $method,$method_short in (margin,'m'),(padding,'p') { 45 | @for $i from 0 through 200 { 46 | @if $i % 5 == 0 { 47 | .#{$method_short}#{$i}-#{$media} { #{$method}: #{$i}px !important; } 48 | @if $media == 'xs'{ 49 | .#{$method_short}#{$i} { #{$method}: #{$i}px !important; } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | @mixin method_loop($media) { 56 | @each $method,$method_short in (margin,'m'),(padding,'p') { 57 | @for $i from 0 through 200 { 58 | @each $direction,$direction_short in (right,'r'),(left,'l'),(top,'t'),(bottom,'b') { 59 | @if $i % 5 == 0 { 60 | .#{$method_short}#{$direction_short}#{$i}-#{$media} { #{$method}-#{$direction}: #{$i}px !important; } 61 | @if $media == 'xs'{ 62 | .#{$method_short}#{$direction_short}#{$i} { #{$method}-#{$direction}: #{$i}px !important; } 63 | } 64 | @if $i == 0{ 65 | .#{$method_short}#{$direction_short}n-#{$media} { #{$method}-#{$direction}: inherit !important; } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | @include method_loop('xs'); 73 | @include method_loop_full('xs'); 74 | @include method_loop_two_way('xs'); 75 | 76 | @media (min-width: $screen-sm-min) { 77 | @include method_loop('sm'); 78 | @include method_loop_full('sm'); 79 | @include method_loop_two_way('sm'); 80 | } 81 | 82 | @media (min-width: $screen-md-min) { 83 | @include method_loop('md'); 84 | @include method_loop_full('md'); 85 | @include method_loop_two_way('md'); 86 | } 87 | 88 | @media (min-width: $screen-lg-min) { 89 | @include method_loop('lg'); 90 | @include method_loop_full('lg'); 91 | @include method_loop_two_way('lg'); 92 | } -------------------------------------------------------------------------------- /css/mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin justice-content ($_){ 2 | justify-content:$_ ; 3 | -webkit-justify-content: $_; 4 | } 5 | @mixin align-items ($_){ 6 | align-items:$_ ; 7 | -webkit-align-items: $_; 8 | } 9 | 10 | @mixin border-radius($_){ 11 | -webkit-border-radius:$_; 12 | -moz-border-radius:$_; 13 | border-radius:$_; 14 | } 15 | @mixin border-radius-($_, $__ ,$___){ 16 | border-#{$_}-#{$__}-radius: #{$___}; 17 | -webkit-border-#{$_}-#{$__}-radius: #{$___}; 18 | -moz-border-radius-#{$_}#{$__}: #{$___}; 19 | } 20 | @mixin transition($_) { 21 | -webkit-transition: $_ ; 22 | -moz-transition: $_ ; 23 | -ms-transition: $_ ; 24 | -o-transition: $_ ; 25 | transition: $_ ; 26 | } 27 | 28 | @mixin background-size-cover { 29 | -webkit-background-size:cover; 30 | background-size:cover; 31 | } 32 | @mixin background-size($_) { 33 | -webkit-background-size:$_; 34 | background-size:$_; 35 | } 36 | @mixin square_icon($pixel: 40px){ 37 | font-size:$pixel / 2; 38 | color: $main_red; 39 | background-color: #FFFFFF; 40 | border-radius: $main_radius; 41 | height: $pixel; 42 | line-height: $pixel; 43 | width: $pixel; 44 | text-align: center; 45 | } 46 | @mixin flex{ 47 | display: -webkit-box; 48 | display: -moz-box; 49 | display: -ms-flexbox; 50 | display: -webkit-flex; 51 | display: flex; 52 | } 53 | @mixin flex_($vertical,$horizon){ 54 | @include flex; 55 | -webkit-justify-content: $horizon; 56 | justify-content: $horizon; 57 | -webkit-align-items: $vertical; 58 | align-items: $vertical; 59 | } 60 | @mixin calc($_,$__){ 61 | #{$_}:-moz-calc(#{$__}); 62 | #{$_}:-webkit-calc(#{$__}); 63 | #{$_}:calc(#{$__}); 64 | } 65 | @mixin flex_wrap($_){ 66 | @include flex; 67 | flex-wrap: $_; 68 | -webkit-flex-wrap: $_; 69 | -ms-flex-wrap: $_; 70 | } 71 | @mixin basic_bg($top,$bottom){ 72 | border-top-left-radius: $top; 73 | border-top-right-radius: $top; 74 | border-bottom-right-radius: $bottom; 75 | border-bottom-left-radius: $bottom; 76 | background-color: #FFFFFF; 77 | margin-bottom: 30px; 78 | width: 100%; 79 | padding:30px; 80 | } 81 | @mixin text_overflow($font-size,$line-height){ 82 | font-size: $font-size; 83 | line-height: $line-height; 84 | $lines-to-show: 3; 85 | display: block; /* Fallback for non-webkit */ 86 | display: -webkit-box; 87 | height: $font-size*$line-height*$lines-to-show; /* Fallback for non-webkit */ 88 | margin: 0 auto; 89 | font-size: $font-size; 90 | -webkit-line-clamp: $lines-to-show; 91 | -webkit-box-orient: vertical; 92 | overflow: hidden; 93 | text-overflow: ellipsis; 94 | } -------------------------------------------------------------------------------- /css/offset_right.scss: -------------------------------------------------------------------------------- 1 | .col-xs-offset-right-12 { 2 | margin-right: 100%; 3 | } 4 | .col-xs-offset-right-11 { 5 | margin-right: 91.66666667%; 6 | } 7 | .col-xs-offset-right-10 { 8 | margin-right: 83.33333333%; 9 | } 10 | .col-xs-offset-right-9 { 11 | margin-right: 75%; 12 | } 13 | .col-xs-offset-right-8 { 14 | margin-right: 66.66666667%; 15 | } 16 | .col-xs-offset-right-7 { 17 | margin-right: 58.33333333%; 18 | } 19 | .col-xs-offset-right-6 { 20 | margin-right: 50%; 21 | } 22 | .col-xs-offset-right-5 { 23 | margin-right: 41.66666667%; 24 | } 25 | .col-xs-offset-right-4 { 26 | margin-right: 33.33333333%; 27 | } 28 | .col-xs-offset-right-3 { 29 | margin-right: 25%; 30 | } 31 | .col-xs-offset-right-2 { 32 | margin-right: 16.66666667%; 33 | } 34 | .col-xs-offset-right-1 { 35 | margin-right: 8.33333333%; 36 | } 37 | .col-xs-offset-right-0 { 38 | margin-right: 0; 39 | } 40 | @media (min-width: 768px) { 41 | .col-sm-offset-right-12 { 42 | margin-right: 100%; 43 | } 44 | .col-sm-offset-right-11 { 45 | margin-right: 91.66666667%; 46 | } 47 | .col-sm-offset-right-10 { 48 | margin-right: 83.33333333%; 49 | } 50 | .col-sm-offset-right-9 { 51 | margin-right: 75%; 52 | } 53 | .col-sm-offset-right-8 { 54 | margin-right: 66.66666667%; 55 | } 56 | .col-sm-offset-right-7 { 57 | margin-right: 58.33333333%; 58 | } 59 | .col-sm-offset-right-6 { 60 | margin-right: 50%; 61 | } 62 | .col-sm-offset-right-5 { 63 | margin-right: 41.66666667%; 64 | } 65 | .col-sm-offset-right-4 { 66 | margin-right: 33.33333333%; 67 | } 68 | .col-sm-offset-right-3 { 69 | margin-right: 25%; 70 | } 71 | .col-sm-offset-right-2 { 72 | margin-right: 16.66666667%; 73 | } 74 | .col-sm-offset-right-1 { 75 | margin-right: 8.33333333%; 76 | } 77 | .col-sm-offset-right-0 { 78 | margin-right: 0; 79 | } 80 | } 81 | @media (min-width: 992px) { 82 | .col-md-offset-right-12 { 83 | margin-right: 100%; 84 | } 85 | .col-md-offset-right-11 { 86 | margin-right: 91.66666667%; 87 | } 88 | .col-md-offset-right-10 { 89 | margin-right: 83.33333333%; 90 | } 91 | .col-md-offset-right-9 { 92 | margin-right: 75%; 93 | } 94 | .col-md-offset-right-8 { 95 | margin-right: 66.66666667%; 96 | } 97 | .col-md-offset-right-7 { 98 | margin-right: 58.33333333%; 99 | } 100 | .col-md-offset-right-6 { 101 | margin-right: 50%; 102 | } 103 | .col-md-offset-right-5 { 104 | margin-right: 41.66666667%; 105 | } 106 | .col-md-offset-right-4 { 107 | margin-right: 33.33333333%; 108 | } 109 | .col-md-offset-right-3 { 110 | margin-right: 25%; 111 | } 112 | .col-md-offset-right-2 { 113 | margin-right: 16.66666667%; 114 | } 115 | .col-md-offset-right-1 { 116 | margin-right: 8.33333333%; 117 | } 118 | .col-md-offset-right-0 { 119 | margin-right: 0; 120 | } 121 | } 122 | @media (min-width: 1200px) { 123 | .col-lg-offset-right-12 { 124 | margin-right: 100%; 125 | } 126 | .col-lg-offset-right-11 { 127 | margin-right: 91.66666667%; 128 | } 129 | .col-lg-offset-right-10 { 130 | margin-right: 83.33333333%; 131 | } 132 | .col-lg-offset-right-9 { 133 | margin-right: 75%; 134 | } 135 | .col-lg-offset-right-8 { 136 | margin-right: 66.66666667%; 137 | } 138 | .col-lg-offset-right-7 { 139 | margin-right: 58.33333333%; 140 | } 141 | .col-lg-offset-right-6 { 142 | margin-right: 50%; 143 | } 144 | .col-lg-offset-right-5 { 145 | margin-right: 41.66666667%; 146 | } 147 | .col-lg-offset-right-4 { 148 | margin-right: 33.33333333%; 149 | } 150 | .col-lg-offset-right-3 { 151 | margin-right: 25%; 152 | } 153 | .col-lg-offset-right-2 { 154 | margin-right: 16.66666667%; 155 | } 156 | .col-lg-offset-right-1 { 157 | margin-right: 8.33333333%; 158 | } 159 | .col-lg-offset-right-0 { 160 | margin-right: 0; 161 | } 162 | } -------------------------------------------------------------------------------- /css/rated_star.scss: -------------------------------------------------------------------------------- 1 | [class^="show_rated_"]{ 2 | display: inline-block; 3 | font: normal normal normal 14px/1 FontAwesome; 4 | font-size: 15px; 5 | text-rendering: auto; 6 | -webkit-font-smoothing: antialiased; 7 | moz-osx-font-smoothing: grayscale; 8 | color: $main_red; 9 | margin-top: 5px; 10 | letter-spacing: 5px; 11 | } 12 | .show_rated_0::before{ 13 | content: "\f006 \f006 \f006 \f006 \f006"; 14 | } 15 | .show_rated_0_5::before{ 16 | content: "\f123 \f006 \f006 \f006 \f006"; 17 | } 18 | .show_rated_1::before{ 19 | content: "\f005 \f006 \f006 \f006 \f006"; 20 | } 21 | .show_rated_1_5::before{ 22 | content: "\f005 \f123 \f006 \f006 \f006"; 23 | } 24 | .show_rated_2::before{ 25 | content: "\f005 \f005 \f006 \f006 \f006"; 26 | } 27 | .show_rated_2_5::before{ 28 | content: "\f005 \f005 \f123 \f006 \f006"; 29 | } 30 | .show_rated_3::before{ 31 | content: "\f005 \f005 \f005 \f006 \f006"; 32 | } 33 | .show_rated_3_5::before{ 34 | content: "\f005 \f005 \f005 \f123 \f006"; 35 | } 36 | .show_rated_4::before{ 37 | content: "\f005 \f005 \f005 \f005 \f006"; 38 | } 39 | .show_rated_4_5::before{ 40 | content: "\f005 \f005 \f005 \f005 \f123"; 41 | } 42 | .show_rated_5::before{ 43 | content: "\f005 \f005 \f005 \f005 \f005"; 44 | } 45 | -------------------------------------------------------------------------------- /css/setting.scss: -------------------------------------------------------------------------------- 1 | body{ 2 | font-family: 'Microsoft JhengHei',Tahoma, Helvetica, Arial, "Microsoft Yahei","微软雅黑", STXihei, "华文细黑", sans-serif; 3 | } 4 | //@import "bootstrap-sprockets"; 5 | //@import "bootstrap/variables"; 6 | //@import "bootstrap/mixins"; 7 | //@import "bootstrap/normalize"; 8 | //@import "bootstrap/print"; 9 | //@import "bootstrap/forms"; 10 | //@import "bootstrap/scaffolding"; 11 | //@import "bootstrap/type"; 12 | //@import "bootstrap/grid"; 13 | //@import "bootstrap/component-animations"; 14 | //@import "bootstrap/dropdowns"; 15 | //@import "bootstrap/navs"; 16 | //@import "bootstrap/navbar"; 17 | //@import "bootstrap/carousel"; 18 | //@import "bootstrap/utilities"; 19 | //@import "bootstrap/responsive-utilities"; 20 | -------------------------------------------------------------------------------- /css/svg_ssetting.scss: -------------------------------------------------------------------------------- 1 | .icon_setting{ 2 | @include background_size_cover; 3 | background-position: center; 4 | display: inline-block; 5 | margin-right: 5px; 6 | font-size:inherit; 7 | } 8 | @mixin share_icon($color){ 9 | background-image:url('data:image/svg+xml;utf8, 10 | share icon 11 | Created with Sketch. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | '); 26 | @extend .icon_setting; 27 | width: 1em; 28 | height: 0.9em; 29 | margin-bottom: -3px; 30 | } 31 | .share_icon_white{ 32 | @include share_icon(white); 33 | } 34 | .share_icon_red{ 35 | @include share_icon($main_red); 36 | } -------------------------------------------------------------------------------- /css/tool.scss: -------------------------------------------------------------------------------- 1 | .white{ 2 | color: #FFFFFF; 3 | } 4 | .red{ 5 | color: $main_red; 6 | } 7 | .black{ 8 | color: $main_black; 9 | } 10 | .gray{ 11 | color: #9B9B9B; 12 | } 13 | .orange{ 14 | color: #FF7663; 15 | } 16 | .lighter{ 17 | font-weight: lighter; 18 | } 19 | .normal{ 20 | font-weight: normal; 21 | } 22 | .background_red{ 23 | background-color: $main_red; 24 | } 25 | .background_white{ 26 | background-color: #FFFFFF; 27 | } 28 | .background_black{ 29 | background-color: #444444; 30 | } 31 | .border_red{ 32 | border: 1px solid $main_red ; 33 | } 34 | .border_black{ 35 | border:1px solid #444444; 36 | } 37 | .sub_link{ 38 | color: #003470; 39 | text-decoration: underline; 40 | } 41 | .vertical_align{ 42 | vertical-align: middle; 43 | } 44 | .black_border_block{ 45 | @extend .border_black; 46 | margin:15px 25px; 47 | padding: 30px; 48 | } 49 | .l_line:before{ 50 | @extend .red; 51 | content:'|'; 52 | font-size:16px; 53 | margin: 0 15px; 54 | } 55 | .cursor_pointer{ 56 | cursor: pointer; 57 | } 58 | .background_img_setting{ 59 | @include background_size_cover; 60 | background-position: center; 61 | } 62 | .border_main_radius{ 63 | @include border_radius($main_radius); 64 | } 65 | .border_sub_radius{ 66 | @include border_radius($sub_radius); 67 | } 68 | .border_circle{ 69 | @include border_radius(50%); 70 | } 71 | .border_none_radius{ 72 | @include border_radius(0px); 73 | } 74 | .fluid{ 75 | width: 100%; 76 | } 77 | .small_btn{ 78 | width: 84px; 79 | height: 32px; 80 | } 81 | .square_icon { 82 | @include square_icon; 83 | } 84 | .flex{ 85 | @include flex; 86 | } 87 | .flex_wrap{ 88 | @include flex_wrap(wrap); 89 | } 90 | .flex_space_around{ 91 | @include flex_(inherit,space-around); 92 | } 93 | .vertical_space_around{ 94 | @extend .flex; 95 | @extend .flex_space_between; 96 | -ms-flex-direction: column; 97 | -webkit-flex-direction: column; 98 | flex-direction: column; 99 | } 100 | .flex_space_between{ 101 | @include flex_(inherit,space-between); 102 | } 103 | .flex_center_start{ 104 | @include flex_(inherit,flex-start); 105 | } 106 | .flex_center{ 107 | @include flex_(center,center); 108 | } 109 | .flex_vertical_center{ 110 | @include flex_(center,inherit); 111 | } 112 | .bold{ 113 | font-weight: bold; 114 | } 115 | .red_line{ 116 | border-bottom: 1px solid $main_red; 117 | width: 100%; 118 | margin:15px auto; 119 | display: block; 120 | } 121 | .gray{ 122 | color: #D4D5D6; 123 | } 124 | .gray_line{ 125 | border-bottom: 1px solid #D4D5D6; 126 | width: 100%; 127 | margin:15px auto; 128 | display: block; 129 | } 130 | .absolute_center{ 131 | position: absolute; 132 | left: 50%; 133 | transform: translateX(-50%); 134 | } 135 | .btn_setting{ 136 | @extend .border_sub_radius; 137 | @extend .tac; 138 | @extend .cursor_pointer; 139 | display: inline-block; 140 | font-weight: inherit; 141 | font-size:1em; 142 | padding: 0 15px; 143 | line-height: 40px; 144 | min-width: 100px; 145 | height: 40px; 146 | } 147 | .ui.button.my_btn,.my_btn{ 148 | @extend .background_red; 149 | @extend .white; 150 | @extend .border_red; 151 | @extend .btn_setting; 152 | } 153 | .ui.button.my_btn_reserve,.my_btn_reserve{ 154 | @extend .background_white; 155 | @extend .red; 156 | @extend .border_red; 157 | @extend .btn_setting; 158 | } 159 | .my_black_btn{ 160 | @extend .background_black; 161 | @extend .white; 162 | @extend .border_black; 163 | @extend .btn_setting; 164 | } 165 | .my_black_btn_reserve{ 166 | @extend .border_black; 167 | @extend .background_white; 168 | @extend .black; 169 | @extend .btn_setting; 170 | } 171 | .four_btn{ 172 | @extend .df; 173 | [class*=_btn],[class*=_btn_reserve]{ 174 | @include calc(width,'100% / 4'); 175 | margin: 5px; 176 | i{ 177 | font-size: 40px; 178 | } 179 | p{ 180 | line-height: 10px; 181 | margin: 0; 182 | } 183 | } 184 | } 185 | //----------------load more ----------------- 186 | //
187 | // 188 | //
189 | 190 | .load_more { 191 | display: block; 192 | text-align: center; 193 | input { 194 | @extend .background_red; 195 | @extend .white; 196 | @extend .border_sub_radius; 197 | @extend .border_red; 198 | font-weight: inherit; 199 | font-size: 1em; 200 | width: 175px; 201 | height: 40px; 202 | } 203 | } 204 | .square_img{ 205 | position: relative; 206 | width: 100%; 207 | padding-top: 100%; 208 | overflow: hidden; 209 | @extend .background_img_setting; 210 | img{ 211 | position: absolute; 212 | left: 0; 213 | right: 0; 214 | top: 0; 215 | bottom: 0; 216 | width: 100%; 217 | height: 100%; 218 | } 219 | } 220 | @mixin align_two_side{ 221 | &:after,&:before{ 222 | content:' '; 223 | display: table; 224 | } 225 | &:after{ 226 | clear: both; 227 | } 228 | &>:first-child{ 229 | float: left; 230 | } 231 | &>:last-child{ 232 | float: right; 233 | } 234 | } 235 | .align_two_side{ 236 | @include align_two_side; 237 | } 238 | .align_two_side_sm{ 239 | @include align_two_side; 240 | } 241 | @media (max-width: $screen-xs-max ){ 242 | [class*=basic_bg]{ 243 | .four_btn{ 244 | @include calc(width,'100% + 10px'); 245 | margin-left: -5px; 246 | padding: 0; 247 | [class*=_btn],[class*=_btn_reserve]{ 248 | margin: 0; 249 | border-right: none; 250 | } 251 | } 252 | } 253 | .align_two_side_sm{ 254 | & > :last-child,& > :first-child{ 255 | float: inherit; 256 | display: block; 257 | } 258 | } 259 | .black_border_block{ 260 | margin: -1px 0 0 -20px; 261 | @include calc(width,'100% + 40px'); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /git/git.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lustan3216/BlogArticle/949e997cbfd64bac611bf2a81bff04f47c364de8/git/git.md -------------------------------------------------------------------------------- /html/fontawesome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /jquery/ajax.md: -------------------------------------------------------------------------------- 1 | If u use jquery ajax to send "DELETE" to rails 2 | U need to use 3 | **data: {"_method":"delete"}** 4 | 5 | Dosen't work right below method. 6 | **type : 'DELETE'** 7 | 8 | ```js 9 | $.ajax({ 10 | type: 'POST', 11 | url: "/likes/"+$(this).data('product-id'), 12 | data: {"_method":"delete"}, 13 | success: function(){ 14 | console.log(321); 15 | _this.removeClass('liked').addClass('unliked') 16 | } 17 | }) 18 | ``` 19 | 20 | 21 | 如果有時候js.erb一直沒有反應,就要去查format是不是空的 22 | 或是直接在ajax的url網址後面加.js 23 | ```js 24 | $.ajax({ 25 | type: 'get', 26 | url: '<%= restaurant_path(@restaurant) %>'+'.js', 27 | data: {date:date} 28 | }); 29 | ``` -------------------------------------------------------------------------------- /jquery/get_url_path.js: -------------------------------------------------------------------------------- 1 | 2 | alert('location.href: '+location.href); //輸出値為 location.href: http://www.wibibi.com/test.html?tid=222#333 3 | alert('location.protocol: '+location.protocol); //輸出値為 location.protocol: http: 4 | alert('location.hostname: '+location.hostname); //輸出値為 location.hostname: www.wibibi.com 5 | alert('location.host: '+location.host); //輸出値為 location.host: www.wibibi.com 6 | alert('location.port: '+location.port); //輸出値為 80 7 | alert('location.pathname: '+location.pathname); //輸出値為 location.pathname: /test.html 8 | alert('location.search: '+location.search); //輸出値為 location.search: ?tid=222 9 | alert('location.hash: '+location.hash); //輸出値為 location.hash: #333 10 | -------------------------------------------------------------------------------- /jquery/image_show_immediate.md: -------------------------------------------------------------------------------- 1 | **Show pic immediately with image upload** 2 | 3 | _is trick not even upload yet skill!_ 4 | 5 | ``` 6 | $(function() { 7 | $('#pictureInput').on('change', function(event) { 8 | var files = event.target.files; 9 | var image = files[0] 10 | var reader = new FileReader(); 11 | reader.onload = function(file) { 12 | var img = new Image(); 13 | console.log(file); 14 | img.src = file.target.result; 15 | $('#target').html(img); 16 | } 17 | reader.readAsDataURL(image); 18 | console.log(files); 19 | }); 20 | }); 21 | 22 |
23 | 24 |
25 |
26 |
27 | ``` 28 | -------------------------------------------------------------------------------- /js/audio_play_bar.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | <% if @post.audio.present? %> 7 | 11 | <% end %> 12 |
13 |
14 |
15 |
16 | 17 |
18 | 開啟App 19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 | 163 | 164 | -------------------------------------------------------------------------------- /js/blob.js: -------------------------------------------------------------------------------- 1 | // HTML5 canvas, save jpeg blob and restore to canvas from blob 2 | function blob2canvas(canvas,blob){ 3 | var img = new Img; 4 | var ctx = canvas.getContext('2d'); 5 | img.onload = function () { 6 | ctx.drawImage(img,0,0); 7 | } 8 | img.src = blob; 9 | } 10 | 11 | // The blob was received when calling canvas.toDataURL("image/jpeg") -------------------------------------------------------------------------------- /js/clear_hover.md: -------------------------------------------------------------------------------- 1 | 想要清掉hover可以用下面的程式碼技巧 2 | 原理只是把該元素刪除又馬上補回去 這樣就會清掉hover狀態 3 | 4 | 在手機版上常需要用到 5 | 6 | ```js 7 | $('collect_product_btn button,.follow_designer').click(function(){ 8 | var el = this; 9 | var par = el.parentNode; 10 | var next = el.nextSibling; 11 | par.removeChild(el); 12 | setTimeout(function() {par.insertBefore(el, next);}, 0) 13 | }) 14 | ``` -------------------------------------------------------------------------------- /js/css_block_debug.md: -------------------------------------------------------------------------------- 1 | 108 byte version 2 | ``` 3 | [].forEach.call($$("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)}) 4 | ``` 5 | 131 byte version 6 | ``` 7 | [].forEach.call(document.querySelectorAll("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)}) 8 | ``` -------------------------------------------------------------------------------- /js/get_view_height_width.js: -------------------------------------------------------------------------------- 1 | function getInfo() 2 | { 3 | var s = ""; 4 | s += " 網頁可見區域寬:"+ document.body.clientWidth; 5 | s += " 網頁可見區域高:"+ document.body.clientHeight; 6 | s += " 網頁可見區域寬:"+ document.body.offsetWidth + " (包括邊線和捲軸的寬)"; 7 | s += " 網頁可見區域高:"+ document.body.offsetHeight + " (包括邊線的寬)"; 8 | s += " 網頁正文全文寬:"+ document.body.scrollWidth; 9 | s += " 網頁正文全文高:"+ document.body.scrollHeight; 10 | s += " 網頁被卷去的高(ff):"+ document.body.scrollTop; 11 | s += " 網頁被卷去的高(ie):"+ document.documentElement.scrollTop; 12 | s += " 網頁被卷去的左:"+ document.body.scrollLeft; 13 | s += " 網頁正文部分上:"+ window.screenTop; 14 | s += " 網頁正文部分左:"+ window.screenLeft; 15 | s += " 螢幕解析度的高:"+ window.screen.height; 16 | s += " 螢幕解析度的寬:"+ window.screen.width; 17 | s += " 螢幕可用工作區高度:"+ window.screen.availHeight; 18 | s += " 螢幕可用工作區寬度:"+ window.screen.availWidth; 19 | s += " 你的螢幕設置是 "+ window.screen.colorDepth +" 位彩色"; 20 | s += " 你的螢幕設置 "+ window.screen.deviceXDPI +" 像素/英寸"; 21 | s += " 這個elecment離上螢幕匡的邊 "+ some_element.getBoundingClientRect().top ; 22 | //alert (s); 23 | } 24 | //get this x,y座標 25 | var X= this.getBoundingClientRect().left+document.documentElement.scrollLeft; 26 | var Y =this.getBoundingClientRect().top+document.documentElement.scrollTop; 27 | 28 | 29 | // getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。 30 | // getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)。 31 | // 该函数返回一个Object对象,该对象有6个属性:top,lef,right,bottom,width,height; 32 | // 这里的top、left和css中的理解很相似,width、height是元素自身的宽高,但是right,bottom和css中的理解有点不一样。 33 | // right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。 34 | -------------------------------------------------------------------------------- /js/like_super.js: -------------------------------------------------------------------------------- 1 | someFunction = function(str) { 2 | console.log('Original function: ' + str); 3 | } 4 | 5 | someFunction = (function() { 6 | var cached_function = someFunction; 7 | 8 | return function(str) { 9 | console.log('New function before: ' + str); 10 | 11 | cached_function.apply(this, arguments); // use .apply() to call it 12 | 13 | console.log('New function after: ' + str); 14 | }; 15 | }()); 16 | 17 | someFunction('It works!'); 18 | -------------------------------------------------------------------------------- /js/search_input_timer.js: -------------------------------------------------------------------------------- 1 | //清除當下的timer 2 | var delayTimer; 3 | 4 | clearTimeout(delayTimer); 5 | delayTimer = setTimeout(function() { 6 | $.ajax({ 7 | url: '/api/v1/check_delivery_location', 8 | dataType: "json", 9 | data: { 10 | text: location_val, 11 | restaurant_id: get_restaurant_id() 12 | }, 13 | type: 'GET', 14 | complete:function(data){ 15 | $('.alert_message').removeClass('hidden') 16 | $('#alert_notice').html($.parseJSON(data.responseText).message) 17 | } 18 | }) 19 | }, 1000); 20 | 21 | 22 | // 清除所有的timer 23 | var timers = []; 24 | // add a timer to the array 25 | timers.push(setTimeout(someFunc, 1000)); 26 | // clear all timers in the array 27 | for (var i = 0; i < timers.length; i++) 28 | { 29 | clearTimeout(timers[i]); 30 | } -------------------------------------------------------------------------------- /js/timer.js: -------------------------------------------------------------------------------- 1 | function Timer(fn, t) { 2 | var timerObj = setInterval(fn, t); 3 | 4 | this.stop = function() { 5 | if (timerObj) { 6 | clearInterval(timerObj); 7 | timerObj = null; 8 | } 9 | return this; 10 | } 11 | 12 | // start timer using current settings (if it's not already running) 13 | this.start = function() { 14 | if (!timerObj) { 15 | this.stop(); 16 | timerObj = setInterval(fn, t); 17 | } 18 | return this; 19 | } 20 | 21 | // start with new interval, stop current interval 22 | this.reset = function(newT) { 23 | t = newT; 24 | return this.stop().start(); 25 | } 26 | } -------------------------------------------------------------------------------- /js/watch.js: -------------------------------------------------------------------------------- 1 | /* 2 | * object.watch polyfill 3 | * 4 | * 2012-04-03 5 | * 6 | * By Eli Grey, http://eligrey.com 7 | * Public Domain. 8 | * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 9 | */ 10 | 11 | // object.watch 12 | if (!Object.prototype.watch) { 13 | Object.defineProperty(Object.prototype, "watch", { 14 | enumerable: false 15 | , configurable: true 16 | , writable: false 17 | , value: function (prop, handler) { 18 | var 19 | oldval = this[prop] 20 | , newval = oldval 21 | , getter = function () { 22 | return newval; 23 | } 24 | , setter = function (val) { 25 | oldval = newval; 26 | return newval = handler.call(this, prop, oldval, val); 27 | } 28 | ; 29 | 30 | if (delete this[prop]) { // can't watch constants 31 | Object.defineProperty(this, prop, { 32 | get: getter 33 | , set: setter 34 | , enumerable: true 35 | , configurable: true 36 | }); 37 | } 38 | } 39 | }); 40 | } 41 | 42 | // object.unwatch 43 | if (!Object.prototype.unwatch) { 44 | Object.defineProperty(Object.prototype, "unwatch", { 45 | enumerable: false 46 | , configurable: true 47 | , writable: false 48 | , value: function (prop) { 49 | var val = this[prop]; 50 | delete this[prop]; // remove accessors 51 | this[prop] = val; 52 | } 53 | }); 54 | } -------------------------------------------------------------------------------- /rails/asset_boost_track.rb: -------------------------------------------------------------------------------- 1 | 小技巧是可以將 js 和 css code 放進 Asset Pipeline 裡面,但是只有特定頁面才會作用(這一招不管 Turbolinks 有沒有移除都適用)。方法是每一頁的 body 標籤加上 id,修改 app/views/layout/application.html.erb: 2 | 3 | 4 | 這樣如果 welcome controller 的 index 頁面的話,就會產生出 的標籤。如此這樣我們的 css 或 javascript 就可以定位了。例如可以在上述的 assets/javascript/common.js 寫: 5 | 6 | $(document).on("turbolinks:load", function() { 7 | if ( $("#welcome-index").length > 0 ) { 8 | console.log("this is welcome-index page"); 9 | } 10 | }) -------------------------------------------------------------------------------- /rails/cache_asset_pipline_known.rb: -------------------------------------------------------------------------------- 1 | 此網址是參考文章,寫得非常好 2 | # http://blog.techbridge.cc/2017/06/17/cache-introduction/ 3 | 4 | cache-control public 是可以存在本地、CDN,private 的話可以存在本地但不能存在CDN,max-age 就是指可以存活多久 Cache-Control: max-age=30,就是存活30秒 5 | 6 | Etag 像是該檔案的ID,http上使用的,但是該Etag是會變的,變得時機是該檔案有變更過時。 7 | 8 | Etag跟If-None-Match 是配合使用的,Server 在回傳 Response 的時候帶上Etag表示這個檔案獨有的 hash, 9 | 快取過期後瀏覽器發送If-None-Match詢問 Server 是否有新的資料(不符合這個Etag的資料),有的話就回傳新的,沒有的話就只要回傳 304 就好了。 10 | 11 | 但配合Etag 的cache方式有個不好的地方是,每次都要跟server詢問要不要更新檔案,如果不用更新就吐304, 12 | Rails的方式可以讓檔案都不用詢問server且也知道何時該更新,增加畫面render速度。 13 | 14 | Rails Asset cache(image/js/css等等)的機制是使用cache-control 設定成有效期限是 1 年 且 public, 15 | 這樣所有檔案都會直接拉本機的cache執行不再問server需不需要更新, 16 | 每次頁面都會重新加載,所以當檔案有被更新過時,asset的hash-key就會不一樣(透過MD5編碼 ) 17 | 如果該檔案有被更新過,Asset pipline就會產生新的MD5編碼(模仿Etag),這樣就會去找新的檔案。 18 | e.g [https://www.fusaki.com.tw/assets/application-aa36dfddac96f89542bd893edfd9ed95d4ffebf0696b5cbec522f6f58788309a.js] 19 | 20 | 所以會變成像是index.html每次都會重新詢問server要不要重新加載畫面(Cache-Control:max-age=0, private, must-revalidate), 21 | 假如當下照片的網址是 photo-c96f89542bd8.jpg,他就會去server問第一次,然後就會拿到cache-control:public 一年有效期,第二次訪問時就直接load本地端的, 22 | 假如photo有變更了這樣hash就會變更photo-95d4ffebf069.jpg,這樣他就會重新去server找檔案了。 23 | 24 | 跟普通的Etag實作方式最大差異是,Etag每次都要跟server問需不需要更新,Rails cache實作方式不用。 -------------------------------------------------------------------------------- /rails/parperclip_defalut_img_setting.rb: -------------------------------------------------------------------------------- 1 | has_attached_file :image, 2 | styles: { medium: "300x300>", thumb: "100x100>" }, 3 | default_url: ->(attachment) { ActionController::Base.helpers.asset_path('tmp/a64.png') } -------------------------------------------------------------------------------- /rails/precomplie_setting.rb: -------------------------------------------------------------------------------- 1 | # https://gogojimmy.net/2012/07/03/understand-assets-pipline/ 2 | # 覆寫 assets:precompile 來判斷是否有更新 assets,如果沒有才執行 precompile 3 | namespace :deploy do 4 | namespace :assets do 5 | task :precompile, :roles => :web, :except => { :no_release => true } do 6 | from = source.next_revision(current_revision) 7 | if capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0 8 | run_locally "bundle exec rake assets:precompile" 9 | find_servers_for_task(current_task).each do |server| 10 | run_locally "rsync -vr --exclude='.DS_Store' public/assets #{user}@#{server.host}:#{shared_path}/" 11 | end 12 | else 13 | logger.info "Skipping asset pre-compilation because there were no asset changes" 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /rspec/rspec.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lustan3216/BlogArticle/949e997cbfd64bac611bf2a81bff04f47c364de8/rspec/rspec.md -------------------------------------------------------------------------------- /ruby/http_code_render_and_serialize.rb: -------------------------------------------------------------------------------- 1 | module Render 2 | 3 | HTTP_SUCCESS_CODE = [[200, 'OK'], [204, 'No Content']] 4 | 5 | HTTP_SUCCESS_CODE.each do |array| 6 | define_method(:"render_#{array[0]}") do |data, hash_options = {}, data_options = {}| 7 | render json: { status: 'Success', 8 | message: array[1], 9 | data: serialize_data(data, data_options) 10 | }.merge(hash_options), status: array[0] 11 | end 12 | end 13 | 14 | 15 | HTTP_ERROR_CODE = [[400, 'Bad Request'], [401, 'Unauthorized'], [403, 'Forbidden'], [404, 'Not Found'], 16 | [500, 'Internal Server Error']] 17 | 18 | HTTP_ERROR_CODE.each do |array| 19 | define_method(:"render_#{array[0]}") do |hash_options = {}| 20 | render json: { status: 'Error', 21 | message: array[1] 22 | }.merge(hash_options), status: array[0] 23 | end 24 | end 25 | 26 | private 27 | 28 | def serialize_data(data, options = {}) 29 | serialize_class = serialize_class(data) 30 | if data.respond_to?(:to_ary) 31 | data.map { |record| serialize_class.new(record, options).as_json } 32 | else 33 | serialize_class.new(data, options).as_json 34 | end 35 | end 36 | 37 | def serialize_class(data) 38 | name = data.respond_to?(:to_ary) ? data.table_name : data.class.name 39 | name = name.singularize.capitalize + 'Serializer' 40 | name.constantize 41 | end 42 | end -------------------------------------------------------------------------------- /ruby/plan_model.rb: -------------------------------------------------------------------------------- 1 | class PlainModel 2 | include ActiveModel::Model 3 | include ActiveSupport::Callbacks 4 | include ActiveModel::Validations::Callbacks 5 | define_callbacks :save 6 | 7 | def save 8 | if valid? 9 | run_callbacks :save do 10 | true 11 | end 12 | else 13 | false 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /server/azure_face_detection.md: -------------------------------------------------------------------------------- 1 | ## Face - Detect 2 | 找每個人臉的 特徵 3 | 4 | 年紀 / 性別 / 毛髮 / 化妝 5 | 6 | return faceId / it will expire after 24hours 7 | 8 | ## Face - Find Similar 9 | 如果用detect 搜尋過人臉之後會被存起來,再用 detect 拿到當下照片的faceId 再去faceList 建立名單或是 faceIds array 中查找相似 10 | 11 | ## Face - Group 12 | 暫存faceId 的group會回傳的group會是個array,如果其中的人臉是相同的人會被分在同組,and return messyGroup 13 | 14 | ## Face - Identify 15 | 從person group辨識不認識的人臉,會給出信心指數排名 16 | person group應該要被訓練成可以被辨識的 17 | 1. 可以一次至多10張臉辨識一個group 18 | 2. Face - Find Similar 可以從facelist來辨識 similar 臉,取代person group 19 | 20 | ## Face - Verify 21 | 便是兩張照片是否同一個人 22 | 23 | ## Face List - Add a Face to a Face List post 24 | 被塞進去的臉都會具有一個 targetFace rectangle,新增一個臉進去 faceList 被塞進list裡面的臉都會具有一個presistedDaceId 25 | 1. 要刪除就用Delete 26 | 2. JPEG, PNG GIF BMP 照片須大魚1kb 小於4MB 27 | 3. 可以偵測的face size 36*36 ~4096*4096 28 | 4. 如果多張臉或是被東西擋住也會被視為error 29 | 5. 被指定的方筐如果不是從face detect來的話不保證資料正確性 30 | 31 | Facelist 裡面的資料都不會過期,可以用Find Similar 查找相似臉。 32 | 常用於查找慶祝會,朋友群,家庭群組 33 | face group have a maximum of 1000 faces 34 | 35 | ## Face List - Create a Face List put 36 | 可以創建空的list 附帶名字和userData 37 | 38 | ## Person - Add a Person Face post 39 | 加入一個這個人的辨識圖.這個臉會有個 targetFace rectangle, 這個會return 一個persistedFaceId代表這張臉。 40 | 也可以是用face - detect 偵測臉 41 | 42 | 1. 每個人可以有248張照片 43 | 2. JPEG, PNG GIF BMP 照片須大魚1kb 小於4MB 44 | 3. 可以偵測的face size 36*36 ~4096*4096 45 | 4. 如果多張臉或是被東西擋住也會被視為error 46 | 47 | ## Person - Create a Person post 48 | 可以用name userData 49 | person會被create 在一個person group裡面 50 | 如果有照片沒有主人 就可以create一個person拿來放照片 51 | 免費的等級每個group只能有1000個人,付費的話可以有10000或更多的人數 52 | 53 | ## Person Group - Create a Person Group put 54 | 可以 create 一個 person group 55 | 這個可以被 Face - Identify 用來查詢臉 56 | 57 | ## Person Group - Get Person Group Training Status get 58 | status : person group需要被訓練成successed才可以被 Face - Identify 拿來查找 59 | 60 | ## Person Group - Train Person Group post 61 | 指定 group 進序列開始等待訓練,並不會馬上開始訓練 62 | 訓練完才能開始被 Face - Identify 使用,可以用上面這隻一直去get status 詢問好了沒 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 |
TIERFEATURESPRICE
Face API – FreeUp to 20 transactions per minute30,000 transactions free per month
Face API – StandardUp to 10 transactions per second
0 - 1,000,000 transactionsNT$46.55 per 1,000 transactions
1,000,001 - 5,000,000 transactionsNT$34.14 per 1,000 transactions
5,000,001 - 20,000,000 transactionsNT$20.17 per 1,000 transactions
Face StorageFace storage - images size up to 4 MB eachNT$15.52 per 1,000 images per month
106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /server/elasticsearch.md: -------------------------------------------------------------------------------- 1 | elasticsearch 預設就會對所有的字串做分詞,且會變成「小寫」 2 | 如果不把自動分析關掉的話,你用term去搜尋一定會搜不到東西 3 | 4 | 因為你打大寫,可是他會用小寫去查 5 | 所以為了關掉 6 | 7 | 要先把原本的刪掉 在新增建一個,並改成以下這樣 8 | 9 | ``` 10 | PUT /my_store <2> 11 | { 12 | "mappings" : { 13 | "products" : { 14 | "properties" : { 15 | "productID" : { 16 | "type" : "string", 17 | "index" : "not_analyzed" <3> 18 | } 19 | } 20 | } 21 | } 22 | 23 | } 24 | ``` -------------------------------------------------------------------------------- /server/elk_config_settings.md: -------------------------------------------------------------------------------- 1 | ```json 2 | server { 3 | listen 80; 4 | server_name kibana.inforcharge.com; 5 | rewrite ^ https://$server_name$request_uri? permanent; 6 | 7 | } 8 | server{ 9 | listen 443 ssl http2; 10 | server_name kibana.inforcharge.com 104.199.142.24; 11 | 12 | #auth_basic "Restricted Access"; 13 | #auth_basic_user_file /etc/nginx/.kibana-user; 14 | 15 | ssl on; 16 | ssl_certificate /etc/nginx/ssl/inforcharge.crt; 17 | ssl_certificate_key /etc/nginx/ssl/inforcharge.key; 18 | ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; 19 | ssl_prefer_server_ciphers on; 20 | 21 | location /dashboard/ { 22 | # rewrite ^/kibana/(.*) /$1 break; 23 | proxy_pass http://localhost:5601/; 24 | proxy_redirect http://host:5601/ /dashboard/; 25 | proxy_http_version 1.1; 26 | proxy_set_header Upgrade $http_upgrade; 27 | proxy_set_header Connection 'upgrade'; 28 | proxy_set_header Host $host; 29 | proxy_cache_bypass $http_upgrade; 30 | } 31 | location / { 32 | proxy_pass http://localhost:9200/; 33 | proxy_http_version 1.1; 34 | proxy_set_header Upgrade $http_upgrade; 35 | proxy_set_header Connection 'upgrade'; 36 | proxy_set_header Host $host; 37 | proxy_cache_bypass $http_upgrade; 38 | } 39 | location /logstash/ { 40 | add_header Access-Control-Allow-Origin *; 41 | default_type application/json; 42 | proxy_pass http://localhost:8080/; 43 | proxy_http_version 1.1; 44 | proxy_set_header Upgrade $http_upgrade; 45 | proxy_set_header Connection 'upgrade'; 46 | proxy_set_header Host $host; 47 | proxy_cache_bypass $http_upgrade; 48 | add_header 'Access-Control-Allow-Headers' 'Content-Type'; 49 | } 50 | 51 | 52 | } 53 | 54 | ``` 55 | 56 | ```json 57 | network.bind_host: localhost 58 | network.publish_host: kibana.inforcharge.com 59 | #transport.publish_port: 443 60 | #transport.tcp.port: 443 61 | # Set a custom port for HTTP: 62 | # 63 | http.publish_port: 443 64 | http.port: 9200 65 | #transport.tcp.port: 9201 66 | 67 | ``` 68 | 69 | 70 | ```json 71 | input { 72 | http { 73 | port => 8080 74 | host => "127.0.0.1" 75 | } 76 | } 77 | filter{ 78 | # ruby {code => "require 'pry'; binding.pry"} 79 | if [message] =~ /^\s*$/ { 80 | drop { } 81 | } 82 | 83 | split{ field => "results" } 84 | mutate { 85 | rename => [ 86 | "[results][sn]", "sn", 87 | "[results][ad_id]", "ad_id", 88 | "[results][ad_type]", "ad_type", 89 | "[results][faces_length]", "faces_length", 90 | "[results][male]", "male", 91 | "[results][female]", "female", 92 | "[results][average_age]", "average_age", 93 | "[results][ad_faces_price]", "ad_faces_price", 94 | "[results][ad_impression_price]", "ad_impression_price", 95 | "[results][ad_calculated_faces_price]", "ad_calculated_faces_price", 96 | "[results][ad_click_price]", "ad_click_price", 97 | "[results][faces_data]", "faces_data" 98 | ] 99 | remove_field => "results" 100 | } 101 | } 102 | output{ 103 | #stdout { codec => rubydebug } 104 | # if "_split_type_failure" not in [tags] { 105 | elasticsearch { 106 | index => "ads-%{+YYYY.MM.dd}" 107 | 108 | ``` -------------------------------------------------------------------------------- /server/encrypt_like_pem.md: -------------------------------------------------------------------------------- 1 | 1. 假設你先在使用者電腦localstorage 存著 localstorage.Auth = ‘ABC’ (這個ABC裡面可以加一些expired_time,or 你想要的uniq值) 2 | 3 | 2. 那他登入前會帶著 Auth,不管裡面是什麼值,只要Rails認得 ABC 他就覺得這是我認識的人,我要給他許可權限。 4 | 5 | 3. 那RAILS 就會用,IP、瀏覽器資訊、時間、Rails的sercret key,做加密變成一個「好像是憑證的東西」,再把這個字串丟回給頁面用JS 用locastroage存起來。 6 | 7 | 4. 然後以後每次有帶這個「好像是憑證的東西」,Rails就會先用 IP、瀏覽器資訊、時間、Rails的sercret key再加密,看這個結果會不會跟「好像是憑證的東西」一樣,一樣就通過。 8 | 9 | 5. 這樣加密邏輯是做在後端,前端也只知道你會丟Auth,不會知道你是用IP和瀏覽器資訊做加密的。 10 | 換去別的電腦也會因為瀏覽器資訊、IP不一樣所以在步驟4 RailS再驗證的時候就不合格 11 | 12 | 6. 假設你要讓所有「好像是憑證的東西」失效,把Rails的sercret key改掉就可以了 13 | 14 | 最一開始要發可以「有權限拿「好像是憑證的東西」」的那個字串 15 | 可以做成Emails的方式寄給那個人開,這個字串裡面要有expried_time,不然會換別人拿去開。 16 | 17 | 打開會跳掉那個網站裡面,然後最開始作剛剛上面那些事。 18 | -------------------------------------------------------------------------------- /server/nginx_site_enable_yml.md: -------------------------------------------------------------------------------- 1 | ``` 2 | upstream inforcharge_sock { 3 | server unix:/var/tmp/nginx.sock fail_timeout=0; 4 | } 5 | 6 | server { 7 | listen 80 default_server; 8 | listen [::]:80 default_server ipv6only=on; 9 | 10 | root /home/deployer/inforcharge/current/public; 11 | 12 | # Make site accessible from http://localhost/ 13 | server_name 54.169.174.47; 14 | 15 | 16 | location / { 17 | proxy_redirect off; 18 | proxy_set_header Host $host; 19 | proxy_set_header X-Forwarded-Host $host; 20 | proxy_set_header X-Forwarded-Server $host; 21 | proxy_set_header X-Real-IP $remote_addr; 22 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 23 | proxy_buffering on; 24 | proxy_pass http://inforcharge_sock; 25 | } 26 | 27 | location ~ ^/assets/ { 28 | expires 1y; 29 | add_header Cache-Control public; 30 | add_header ETag ""; 31 | break; 32 | } 33 | 34 | location ~ ^/data/ { 35 | expires 1y; 36 | add_header Cache-Control public; 37 | add_header ETag ""; 38 | break; 39 | } 40 | 41 | location ~* \.(?:htm|pdf|svg|ico)$ { 42 | expires 1y; 43 | add_header Cache-Control public; 44 | add_header ETag ""; 45 | break; 46 | } 47 | } 48 | 49 | server { 50 | listen 443; 51 | listen [::]:443 ipv6only=on; 52 | server_name 54.169.174.47; 53 | 54 | root /home/deployer/inforcharge/current/public; 55 | 56 | ssl on; 57 | ssl_certificate /etc/nginx/ssl/ssl-bundle2.crt; 58 | ssl_certificate_key /etc/nginx/ssl/inforcharge.key; 59 | 60 | ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; 61 | ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; 62 | ssl_prefer_server_ciphers on; 63 | 64 | location ~ ^/assets/ { 65 | expires 1y; 66 | add_header Cache-Control public; 67 | add_header ETag ""; 68 | break; 69 | } 70 | 71 | location ~ ^/data/ { 72 | expires 1y; 73 | add_header Cache-Control public; 74 | add_header ETag ""; 75 | break; 76 | } 77 | 78 | location / { 79 | proxy_redirect off; 80 | proxy_set_header Host $host; 81 | proxy_set_header X-Forwarded-Host $host; 82 | proxy_set_header X-Forwarded-Server $host; 83 | proxy_set_header X-Real-IP $remote_addr; 84 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 85 | proxy_buffering on; 86 | proxy_pass http://inforcharge_sock; 87 | } 88 | 89 | location ~* \.(?:htm|pdf|ico|svg)$ { 90 | expires 1y; 91 | add_header Cache-Control public; 92 | add_header ETag ""; 93 | break; 94 | } 95 | 96 | location /download-app/c209r { 97 | return 301 https://www.inforcharge.com/download/c209r; 98 | } 99 | location /privacy-policy/c98r { 100 | return 301 https://www.inforcharge.com/privacy/c98r; 101 | } 102 | location /rate/c1r55 { 103 | return 301 https://www.inforcharge.com/rate-x/c1r55; 104 | } 105 | 106 | } 107 | ``` -------------------------------------------------------------------------------- /sql/remote_to_server_database.md: -------------------------------------------------------------------------------- 1 | http://zackwang.blogspot.tw/2013/11/mysql.html 2 | http://eportfolio.lib.ksu.edu.tw/~T093000170/blog?node=000000174 3 | 4 | GRANT ALL PRIVILEGES ON food_p.* TO 161.202.37.152 IDENTIFIED BY 'PassWord' WITH GRANT OPTION; 5 | 6 | GRANT ALL PRIVILEGES ON food_p.* TO ‘root'@'161.202.37.152’ IDENTIFIED BY ‘12345678’ WITH GRANT OPTION; -------------------------------------------------------------------------------- /sql/set_character.md: -------------------------------------------------------------------------------- 1 | 改掉 原本的character 2 | 3 | ```sql 4 | ALTER TABLE featured_links CONVERT TO CHARACTER SET utf8mb4; 5 | ``` 6 | --------------------------------------------------------------------------------