├── .gitignore ├── README.md ├── freakdesign_custom_fields.css ├── freakdesign_custom_fields.load.js ├── freakdesign_custom_fields.min.js └── installation.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Packages 2 | 3 | *.7z 4 | *.dmg 5 | *.gz 6 | *.iso 7 | *.jar 8 | *.rar 9 | *.tar 10 | *.zip 11 | 12 | # Specific Files 13 | 14 | freakdesign_custom_fields.js 15 | api.js 16 | bookmarklet.txt 17 | .DS_Store 18 | .DS_Store? 19 | ._* 20 | .Spotlight-V100 21 | .Trashes 22 | ehthumbs.db 23 | Thumbs.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Shopify custom fields 2 | ===================== 3 | 4 | ![My image](https://freakdesign-us.s3.amazonaws.com/shopify/custom_fields/i/custom_fields_lrg.png) 5 | 6 | This a javascript tool to emulate Custom Fields within the Shopify dashboard. The main use would be for Shopify designers and developers wanting to give their clients a simple way to edit metafields with less confusion. 7 | 8 | Do note that there's no interface for a Store Owner to make any new fields using this (simply to avoid explosions) so it's up to you - the developer - to help add them. To add the required metafields you'll need to either use [ShopifyFD](http://shopify.freakdesign.com.au/), the [Shopify API](http://docs.shopify.com/api/metafield), or a metafield [app](https://apps.shopify.com/) of your choice. 9 | 10 | 11 | Installation and help 12 | --------------------- 13 | 14 | tl;dr Use the [Chrome Extension](https://chrome.google.com/webstore/detail/custom-fields-for-shopify/alfplfpobekffinigeidgmmfjollghln). 15 | 16 | The Chrome Extension is simply a helper script that loads the files from here. If you don't run Chrome or just prefer to load via a bookmarklet you can follow the instructions on [this page](https://rawgithub.com/freakdesign/shopify-custom-fields/master/installation.html). 17 | 18 | A very basic help guide is [available](https://freakdesign-us.s3.amazonaws.com/shopify/custom_fields/freakdesign-custom-fields-for-shopify-guide.pdf). 19 | 20 | 21 | Support Development 22 | ------------------- 23 | 24 | If this tool makes you look awesome to your paying customer or helped you land that project, [consider leaving me a tip](http://freakdesign.com.au/pages/shopify-custom-fields). 25 | 26 | 27 | Exclusions / notes 28 | ------------------ 29 | 30 | * This tool will NOT show metafields under the Global namespace. This is more of a sanity check than anything else. 31 | * Custom field whitelist is loaded once on load. If you change the whitelist after loading it, you'll need to force refresh. 32 | 33 | 34 | Custom field markers 35 | -------------------- 36 | 37 | Add these strings into the value (or key) for added magic. Not all of these work yet so consider them a suggestion only that may change at any time. 38 | 39 | * "[a]": limit display to articles only 40 | * "[c]": limit display to collections only 41 | * "[cu]": limit display to customers only 42 | * "[g]": limit display to pages only 43 | * "[o]": limit display to orders only 44 | * "[p]": limit display to products only 45 | 46 | * "[_c]": mark as a collection field 47 | * "[_f]": mark as a file field 48 | * "[_i]": mark as an integer field 49 | * "[_g]": mark as a page field 50 | * "[_p]": mark as a product field 51 | * "[_n]": mark as a number field 52 | * "[_d]": mark as a date field 53 | * "[_co]": mark as a color field 54 | -------------------------------------------------------------------------------- /freakdesign_custom_fields.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | ############# 6 | ## *## 7 | # % **# 8 | # %%% ***# 9 | # %%F%D%% ****# 10 | # %%% *****# 11 | # ### % ###***# 12 | # # #### #### #**# 13 | # # # # #**# 14 | # ##### # # #####***# 15 | # # # *******# 16 | ### # **# ### 17 | # - - - - - - # 18 | | | | | | | | 19 | 20 | freakdesign.com 21 | 22 | */ 23 | 24 | #freakdesign_main_button{background: #D81965;color: #fff;display: block;font-size: 12px;line-height: 40px;text-align: center;} 25 | 26 | .freakdesign_custom_fields .black-header{border-top:3px solid #d82366;} 27 | .freakdesign_custom_fields .custom_fields_box .content{position:relative;} 28 | .freakdesign_custom_fields .custom_fields_box .half {margin-bottom:1em;width:49%;float:left;} 29 | .freakdesign_custom_fields .custom_fields_box .half:nth-child(odd){clear:left;} 30 | .freakdesign_custom_fields .custom_fields_box .half:nth-child(even){margin-left:2%;} 31 | .freakdesign_custom_fields .custom_fields_box label{border-bottom: 1px dotted #ccc;margin-bottom:5px!important;} 32 | .freakdesign_custom_fields .custom_fields_box label span.block{float:none;display:block;font-size:85%;min-height: 1.5em} 33 | .freakdesign_custom_fields input[data-cffield="select"], .freakdesign_custom_fields input[data-cffield="file"]{width:50%;} 34 | .freakdesign_custom_fields .box-details .custom_fields_box {margin-top:1.5em;margin-left: -4px;} 35 | .freakdesign_custom_fields .custom-fields-content .next-card__section { 36 | padding: 0 0 10px!important; 37 | border-top:1px solid #eee;margin-top:20px 38 | } 39 | .freakdesign_custom_fields .customfield_btn{ 40 | background: #D81965; 41 | border-color: #A9124E; 42 | margin-left: .25em; 43 | } 44 | .freakdesign_custom_fields .customfield_btn:hover, .freakdesign_custom_fields .customfield_btn:focus{ 45 | background: #D81965; 46 | border-color: #A9124E; 47 | } 48 | .modalWindow {position: fixed;top: 0;right: 0;bottom: 0;left: 0;background: rgba(1, 12, 2, 0.7);z-index: 99999;display:none;text-align:center;} 49 | .modalWindow .span1, .modalWindow .span2, .modalWindow .span3, .modalWindow .half{float:left;padding:0;} 50 | .modalWindow .span1 {width:33.332%;} 51 | .modalWindow .span2 {width:66.665%;} 52 | .modalWindow .half {width:50%;} 53 | .modalWindow .active {display:block;} 54 | .modalWindow p {margin-bottom:1em;} 55 | .modalWindow > div {width: 500px;position: relative;margin: 10% auto;background: #fff;border-radius: 3px;padding:1em;text-align: left;box-shadow: 0 0 15px rgba(0,0,0,.5);} 56 | .modalWindow .content li{margin-bottom: 1em;} 57 | .modalWindow .content > div {max-height:400px;overflow:auto;} 58 | .modalWindow .close-modal{position:absolute;background:#121212;color:#fff;border:1px solid #000;width:16px;height:16px;display:inline-block;line-height:1em;text-align:center;text-decoration:none;top:1em;right:1em;border-radius:50%;font-weight: bold;font-size: 1em;} 59 | .modalWindow .close-modal:hover{background:red;color:#fff;border-color:red;} 60 | .modalWindow header{border-bottom:1px solid #ccc;margin:0 0 .5em;padding:0 2em .25em 0;min-height: .25em;} 61 | .modalWindow td{vertical-align: top;} 62 | .modalWindow .warning{background:red;padding:.25em;color:#fff;line-height:1.3;margin:0 0 .5em;} 63 | .modalWindow ul{padding-left: 1em;} 64 | 65 | .fadein{-webkit-animation: fade-in .25s linear;-moz-animation: fade-in .25s linear;-o-animation: fade-in .25s linear;animation: fade-in .25s linear;} 66 | .fadeinslow{-webkit-animation: fade-in 1s linear;-moz-animation: fade-in 1s linear;-o-animation: fade-in 1s linear;animation: fade-in 1s linear;} 67 | 68 | .animated { 69 | -webkit-animation-duration: 1s; 70 | animation-duration: 1s; 71 | -webkit-animation-fill-mode: both; 72 | animation-fill-mode: both; 73 | } 74 | .animated.delayed{ 75 | -webkit-animation-delay:2s; 76 | animation-delay:2s; 77 | } 78 | .animated.infinite { 79 | -webkit-animation-iteration-count: infinite; 80 | animation-iteration-count: infinite; 81 | } 82 | 83 | .bounce { 84 | -webkit-animation-name: bounce; 85 | animation-name: bounce; 86 | -webkit-transform-origin: center bottom; 87 | -ms-transform-origin: center bottom; 88 | transform-origin: center bottom; 89 | } 90 | 91 | @-webkit-keyframes bounce { 92 | 0%, 20%, 53%, 80%, 100% { 93 | -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 94 | transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 95 | -webkit-transform: translate3d(0,0,0); 96 | transform: translate3d(0,0,0); 97 | } 98 | 99 | 40%, 43% { 100 | -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 101 | transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 102 | -webkit-transform: translate3d(0, -30px, 0); 103 | transform: translate3d(0, -30px, 0); 104 | } 105 | 106 | 70% { 107 | -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 108 | transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 109 | -webkit-transform: translate3d(0, -15px, 0); 110 | transform: translate3d(0, -15px, 0); 111 | } 112 | 113 | 90% { 114 | -webkit-transform: translate3d(0,-4px,0); 115 | transform: translate3d(0,-4px,0); 116 | } 117 | } 118 | @keyframes bounce { 119 | 0%, 20%, 53%, 80%, 100% { 120 | -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 121 | transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 122 | -webkit-transform: translate3d(0,0,0); 123 | -ms-transform: translate3d(0,0,0); 124 | transform: translate3d(0,0,0); 125 | } 126 | 127 | 40%, 43% { 128 | -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 129 | transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 130 | -webkit-transform: translate3d(0, -30px, 0); 131 | -ms-transform: translate3d(0, -30px, 0); 132 | transform: translate3d(0, -30px, 0); 133 | } 134 | 135 | 70% { 136 | -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 137 | transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); 138 | -webkit-transform: translate3d(0, -15px, 0); 139 | -ms-transform: translate3d(0, -15px, 0); 140 | transform: translate3d(0, -15px, 0); 141 | } 142 | 143 | 90% { 144 | -webkit-transform: translate3d(0,-4px,0); 145 | -ms-transform: translate3d(0,-4px,0); 146 | transform: translate3d(0,-4px,0); 147 | } 148 | } 149 | 150 | @-webkit-keyframes fade-in 151 | { 152 | from { opacity: 0; } 153 | to { opacity: 1; } 154 | } 155 | @-moz-keyframes fade-in 156 | { 157 | from { opacity: 0; } 158 | to { opacity: 1; } 159 | } 160 | @-o-keyframes fade-in 161 | { 162 | from { opacity: 0; } 163 | to { opacity: 1; } 164 | } 165 | @keyframes fade-in 166 | { 167 | from { opacity: 0; } 168 | to { opacity: 1; } 169 | } 170 | 171 | .fd-cf-btn{ 172 | background: #D81965; 173 | color: #fff; 174 | border-color: #BA188C; 175 | } 176 | 177 | .custom-fields-future-buttons{ 178 | position: absolute; 179 | top: -12px; 180 | right: -12px; 181 | } -------------------------------------------------------------------------------- /freakdesign_custom_fields.load.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | ############# 5 | ## *## 6 | # % **# 7 | # %%% ***# 8 | # %%F%D%% ****# 9 | # %%% *****# 10 | # ### % ###***# 11 | # # #### #### #**# 12 | # # # # #**# 13 | # ##### # # #####***# 14 | # # # *******# 15 | ### # **# ### 16 | # - - - - - - # 17 | | | | | | | | 18 | 19 | freakdesign.com 20 | 21 | CUSTOM FIELDS 22 | 23 | Written by jason from freakdesign 24 | freakdesign.com.au 25 | shopify.freakdesign.com.au 26 | Don't be a tool and pass this off as your own. Contribute! 27 | 28 | */ 29 | var custom_js=document.createElement("script"); 30 | custom_js.type="text/javascript"; 31 | custom_js.src="//rawgithub.com/freakdesign/shopify-custom-fields/master/freakdesign_custom_fields.min.js"; 32 | document.getElementsByTagName('head')[0].appendChild(custom_js) -------------------------------------------------------------------------------- /freakdesign_custom_fields.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | ############# 5 | ## *## 6 | # % **# 7 | # %%% ***# 8 | # %%F%D%% ****# 9 | # %%% *****# 10 | # ### % ###***# 11 | # # #### #### #**# 12 | # # # # #**# 13 | # ##### # # #####***# 14 | # # # *******# 15 | ### # **# ### 16 | # - - - - - - # 17 | | | | | | | | 18 | 19 | freakdesign.com 20 | CUSTOM FIELDS 21 | 22 | */ 23 | (function(){if("undefined"!=typeof Shopify)if("undefined"!=typeof jQuery)if($("html.freakdesign_custom_fields").length)alert("Already loaded the tool?");else{var t=document,x=t.URL;t.documentElement.className+=" freakdesign_custom_fields";if(1
');d&&b.find("header").html("

"+d+"

");c&&(c=$("
",{}).append(c),b.find("div.main.content").append(c));if(g)g=$('×'),g.on("click",function(){a.fd_modal(!1);return!1}),b.find("header").prepend(g).end().fadeIn(); 27 | else b.fadeIn().on("click",function(){a.fd_modal(!1)});$("body").append(b)}else f.off("click").remove()},load_css:function(){if(0===$("#css_custom_fields").length){var b=document.createElement("link");b.type="text/css";b.rel="stylesheet";b.id="css_custom_fields";b.href=a.data("css");document.getElementsByTagName("head")[0].appendChild(b)}},api:function(b){if("object"===typeof b&&"undefined"!==typeof b.url){"function"!==typeof b.callback&&(b.callback=!1);var c="GET",d=250;"undefined"!==typeof b.type&& 28 | (c=b.type);"undefined"!==typeof b.limit&&(d=b.limit);b=b.url.split("?")[0]+"?limit="+d;p&&$.ajax({type:c,url:b,dataType:"json",success:function(b){callback&&callback(b);q&&a.data(q,b)},error:function(){a.notice("Error getting JSON",!0)}})}},custom_fields_preload:function(b){$.ajax({type:"GET",url:"/admin/"+("undefined"!==typeof b?b:"collections")+".json?limit=250",dataType:"json",success:function(b){a.data("collections",b);a.setup_custom_fields(a.data("alpha"))},error:function(){a.notice("Failed to preload required data", 29 | !0)}})},remove_brackets:function(a){a=a.replace(/\[([^\]]*)\]*/g,"");return a=a.charAt(0).toUpperCase()+a.slice(1).replace(/-/g," ").replace(/_/g," ")},save_custom_fields:function(b){if("object"===typeof b)if("undefined"===typeof b.url)a.notice("Error, metafield url not set",!0);else{if("undefined"===typeof b.type){var c=$("div.custom_fields_box.is-product input, div.custom_fields_box.is-product textarea");var d="product"}else c=$(".custom_fields_box.is-variant input, .custom_fields_box.is-variant textarea"), 30 | d="variant";if(c.length){"undefined"===typeof b.callback&&(b.callback=!1);var g=b.t;g.attr("style","color:rgba(0,0,0,0)").addClass("is-loading disabled");var f=function(e,d){"undefined"===typeof e&&(e=0);if("undefined"===typeof d)a.notice("Type unknown",!0);else{var k=c.eq(e),r=k.attr("data-key"),h=k.val(),w="POST",n=k.attr("data-namespace"),m=k.attr("data-type"),l=!1,r={metafield:{namespace:n,key:r,value:h,value_type:m}};0===h.length&&k.attr("data-mid")&&k.attr("data-pid")?(w="DELETE",ajax_url="/admin/"+ 31 | a.data("alpha")+"/"+k.attr("data-pid")+"/metafields/"+k.attr("data-mid")+".json",k.removeAttr("data-pid data-mid")):0===h.length?l=!0:ajax_url=b.url;l?(e++,e

Custom Fields

Manage the custom fields that belong to '+b+'.

');"customers"===a.data("alpha")?(g=$("#customer-profile").parent(),custom_field_panel=custom_field_panel.find(".next-card")):"orders"===a.data("alpha")?(g=$("#order_card"),custom_field_panel=custom_field_panel.find(".next-card")): 34 | "pages"!==a.data("alpha")&&"articles"!==a.data("alpha")&&("collections"===a.data("alpha")?(g=$("div.next-card:not(.next-card--announcement)").eq(0),custom_field_panel=custom_field_panel.find(".next-card")):"products"===a.data("alpha")&&(g=$(".ui-layout__section--primary .ui-layout__item .ui-card:first"),custom_field_panel=custom_field_panel.find(".next-card")));g.length?(a.setting("hideProductCustomFields")||g.after(custom_field_panel),d.length&&"Save"===d.text()&&d.text("Save (without Custom Fields)"), 35 | a.data("fields",[]),$.ajax({type:"GET",url:"/admin/metafields.json?limit=250",dataType:"json",success:function(b){for(var e,d,k="",f="",h=0,g=b.metafields.length;h';l=1'+e+''+b.metafields[h].namespace+"."+b.metafields[h].key+''+a.remove_brackets(b.metafields[h].value)+""):l+('");if("textarea"===m.field)l+= 37 | '';else{var v='type="text"';"date"===m.field&&(v='type="date"');"number"===m.field&&(v='type="number"');l+="'}l+="";"undefined"!==typeof m.variant?f+=l:k+=l}}b=!0;k.length||(k='
'+a.translate("no_fields")+"
",b=!1);custom_field_panel.find(".next-card__section").eq(0).append('
'+k+"
");a.data("variantPanel",f);if(b){custom_field_panel.find('input[data-cftype="collection"]').each(function(){var b=$(this);b.after(a.build_select(b.attr("name"), 39 | "collection"))});custom_field_panel.find('input[data-cftype="linklist"]').each(function(){});custom_field_panel.find('input[data-cftype="product"]').each(function(){});if("undefined"!==a.setting("datalists"))for(e in k=a.setting("datalists"),k)if(f=$('input[data-key="'+e+'"]'),f.length&&"false"===f.attr("data-cftype")){b=$("",{id:"list-"+e});f.attr("list","list-"+e);var h=k[e];for(u in h)h.hasOwnProperty(u)&&(g=$("