Commit 04f2d6f8 by Иван Кубота

it's working

parent 4ca7ca1b
......@@ -16,6 +16,8 @@ NS.apply = function(a,b) {
};
(function(NS, glob, document){
var ArraySlice = [].slice;
var svgNS = 'http://www.w3.org/2000/svg';
var setters = {
......@@ -31,11 +33,11 @@ NS.apply = function(a,b) {
},
attr: function(el, attrName) {
return function(val) {
if(val !== void 0 && val !== false){
el.setAttribute( attrName, val );
}else{
el.removeAttribute(attrName)
}
if(val !== void 0 && val !== false){
el.setAttribute( attrName, val );
}else{
el.removeAttribute(attrName)
}
}
}
};
......@@ -54,23 +56,23 @@ NS.apply = function(a,b) {
if(typeOfType === 'function'){
// factory passed
return type(cfg, [].slice.call(arguments, 2));
return type(cfg, ArraySlice.call(arguments, 2));
}else if(typeof type === 'object' && type.hook){
// hooked future element creation
return type.hook(cfg, [].slice.call(arguments, 2));
return type.hook(cfg, ArraySlice.call(arguments, 2));
}
cfg = cfg || {};
var cls = cfg.cls || cfg['class'] || cfg.className,
style = cfg.style,
style = cfg.style,
attr = cfg.attr || {},
prop = cfg.prop,
on = cfg.on || {},
renderTo = cfg.renderTo,
el = cfg.el || (type in customElementCreate ? customElementCreate[type](type, cfg) : document.createElement( type )),
classList = el.classList;
attr = cfg.attr || {},
prop = cfg.prop,
on = cfg.on || {},
renderTo = cfg.renderTo,
el = cfg.el || (type in customElementCreate ? customElementCreate[type](type, cfg) : document.createElement( type )),
classList = el.classList;
var i, _i, name;
......@@ -166,17 +168,17 @@ NS.apply = function(a,b) {
};
'div,template,span,input,label,canvas,span,textarea,table,tr,td,th,tBody,tHead'.split( ',' ).forEach( function( name ){
D[ name ] = function(){
return domEl.apply( null, [ name ].concat([].slice.call(arguments)))
return domEl.apply( null, [ name ].concat(ArraySlice.call(arguments)))
};
} );
var customElementCreate = {};
var customElementClassNameSetter = {};
var createElementSVG = function(name) {
var el = document.createElementNS( svgNS, name );
el.setAttribute( 'xmlns', svgNS );
return el;
},
var el = document.createElementNS( svgNS, name );
el.setAttribute( 'xmlns', svgNS );
return el;
},
setClassNameSVG = function(el, cls) {
el.setAttribute( 'class', cls );
};
......@@ -188,14 +190,14 @@ NS.apply = function(a,b) {
cfg = {};
}
cfg.el = createElementSVG( name );
return domEl.apply( null, [ null ].concat([].slice.call(arguments)))
return domEl.apply( null, [ null ].concat(ArraySlice.call(arguments)))
};
} );
D.html = function(cfg){
var el = domEl('div', cfg);
el.innerHTML = [].slice.call(arguments,1).join('\n');
return el;
var el = domEl('div', cfg);
el.innerHTML = ArraySlice.call(arguments,1).join('\n');
return el;
};
D.h = domEl;
D.f = function(cfg, children) {
......@@ -224,42 +226,98 @@ NS.apply = function(a,b) {
isInDOM && D._recursiveCmpCall(el, subEl, 'beforeRemoveFromDOM');
el.removeChild(subEl);
isInDOM && D._recursiveCmpCall(el, subEl, 'afterRemoveFromDOM');
}
};
var DFragment = DocumentFragment;
D.insertBefore = function(newChild, refChild) {
var f = document.createDocumentFragment();
D.appendChild(f, newChild);
var el = refChild.parentNode,
subEl = newChild;
var isInDOM = D.isInDOM(el);
isInDOM && D._recursiveCmpCall(el, f, 'beforeAddToDOM');
el.insertBefore( f, refChild );
isInDOM && D._recursiveCmpCall(el, {childNodes: newChild}, 'afterAddToDOM');
};
D.appendChild = function(el, subEl){
var type = typeof subEl;
if(subEl === null){
return ;
}
if( type !== 'object' ){
var notObject = type !== 'object';
var isHook = !notObject && ('hook' in subEl);
if(isHook){
type = 'function'; notObject = true;
}
if( notObject ){
// TODO : add hook
if( type === 'function' ){
var tmp = D.Text('');//( {cls: 'zero-wrapper'} );
el.appendChild( tmp );
var list = [];
subEl( function(){
el.setAttribute('data-hooked', 'yep');
// maybe do it through outer weak map?
el.__un = el.__un || [];
var hookFn;
if(isHook){
hookFn = function(val){
// TODO: append 2 TextNodes and remove children between them
if(el instanceof DFragment){
el = tmp.parentNode;
}
if(!el)
return;
if(list.length === 1){
list[0].textContent = val;
}else{
for( var i = 0, _i = list.length; i < _i; i++ ){
list[ i ].parentNode === el && el.removeChild( list[ i ] );
}
var fragment = document.createDocumentFragment();
D.appendChild( fragment, [].slice.call( arguments ) );
list = [].slice.call(fragment.childNodes);
if(!tmp || !tmp.parentNode)
return;
el.insertBefore(fragment, tmp);
} )
if(el instanceof DFragment){
el = tmp.parentNode;
}
if(!el)
return;
for( var i = 0, _i = list.length; i < _i; i++ ){
list[ i ].parentNode === el && el.removeChild( list[ i ] );
}
var fragment = document.createDocumentFragment();
D.appendChild( fragment, ArraySlice.call( arguments ) );
list = ArraySlice.call( fragment.childNodes );
if( !tmp || !tmp.parentNode )
return;
el.insertBefore( fragment, tmp );
}
};
el.__un.push(subEl.hook( hookFn ));
}else{
hookFn = function(){
// TODO: append 2 TextNodes and remove children between them
if(el instanceof DFragment){
el = tmp.parentNode;
}
if(!el)
return;
for( var i = 0, _i = list.length; i < _i; i++ ){
list[ i ].parentNode === el && el.removeChild( list[ i ] );
}
var fragment = document.createDocumentFragment();
D.appendChild( fragment, ArraySlice.call( arguments ) );
list = ArraySlice.call(fragment.childNodes);
if(!tmp || !tmp.parentNode)
return;
el.insertBefore(fragment, tmp);
};
el.__un.push(subEl( hookFn ));
}
}else if( subEl !== void 0 && subEl !== false && subEl !== null ){
el.appendChild( D.Text( subEl ) );
}
......@@ -267,7 +325,8 @@ NS.apply = function(a,b) {
var isInDOM = D.isInDOM(el);
subEl.dom.__cmp = subEl;
isInDOM && D._recursiveCmpCall(el, subEl.dom, 'beforeAddToDOM');
el.appendChild( subEl.dom );
D.appendChild(el, subEl.dom);
//el.appendChild( subEl.dom );
isInDOM && D._recursiveCmpCall(el, subEl.dom, 'afterAddToDOM');
//subEl
......@@ -432,21 +491,21 @@ NS.apply = function(a,b) {
});
};
var _log = [], later = false,
realLog = function() {
later = false;
var aggregated = _log.reduce(function(s, item) {
(s[item.evt] || (s[item.evt] = [])).push(item);
return s;
}, {});
_log.length = 0;
for(var evt in aggregated){
console.log('DOM:'+evt+' → '+aggregated[evt].map(function(item) {
return item.args.join(' ');
}).join(', '));
}
};
realLog = function() {
later = false;
var aggregated = _log.reduce(function(s, item) {
(s[item.evt] || (s[item.evt] = [])).push(item);
return s;
}, {});
_log.length = 0;
for(var evt in aggregated){
console.log('DOM:'+evt+' → '+aggregated[evt].map(function(item) {
return item.args.join(' ');
}).join(', '));
}
};
var log = function(evt) {
_log.push({type: 'log', evt: evt, args: [].slice.call(arguments, 1)});
_log.push({type: 'log', evt: evt, args: ArraySlice.call(arguments, 1)});
if(!later)
later = setTimeout(realLog, 3000);
......@@ -454,7 +513,8 @@ NS.apply = function(a,b) {
var emptyFn = function() {};
D.Unsubscribe = function(fn) {
this.fn = [fn];
this.fn = [];
fn && this.fn.push(fn);
};
D.Unsubscribe.prototype = {
un: function() {
......@@ -474,12 +534,13 @@ NS.apply = function(a,b) {
}
}
};
var unsubscribable = function(name) {
return function(el, fn) {
return function(el, fn, arg) {
typeof fn !== 'function' && (fn = getCallableFunction(fn));
el.addEventListener(name, fn);
el.addEventListener(name, fn, arg);
return new D.Unsubscribe(function() {
el.removeEventListener(name, fn);
el.removeEventListener(name, fn, arg);
});
};
};
......@@ -490,12 +551,51 @@ NS.apply = function(a,b) {
over: unsubscribable('mouseover'),
};
D.AnimationFrame = function(fn) {
var requested = false,
arg,
update = function() {
fn.call(null, arg);
requested = false;
};
return function(a) {
arg = a;
if(!requested){
requestAnimationFrame(update);
requested = true;
}
};
};
D.overlay = {
inited: false,
show: function() {
this.init();
this.el.style.display = 'block';
},
hide: function() {
this.init();
this.el.style.display = 'none';
},
init: function() {
if(this.inited)
return;
this.inited = true;
this.el = D.div({
renderTo: document.body,
cls: 'D-overlay', style: {display: 'none', position: 'absolute', zIndex:10000, left: 0, right: 0, top: 0, bottom: 0}})
this.el.addEventListener('mousemove', function(e) {
e.preventDefault();
e.stopPropagation();
}, true)
}
};
})(window['NS'], typeof window !== "undefined" ? window :
typeof WorkerGlobalScope !== "undefined" ? self :
typeof global !== "undefined" ? global :
typeof GLOBAL !== "undefined" ? GLOBAL :
Function("return this;")(), document);
typeof GLOBAL !== "undefined" ? GLOBAL :
Function("return this;")(), document);
var D = NS.D,
div = D.div,
......
......@@ -314,4 +314,11 @@ function rgbToHsl(r, g, b) {
}
return [ h, s, l ];
}
function HEX2RGB(hex){
var color = (hex+'').substr( 1 ) || '',
r = parseInt( color[ 0 ] + color[ 1 ], 16 ),
g = parseInt( color[ 2 ] + color[ 3 ], 16 ),
b = parseInt( color[ 4 ] + color[ 4 ], 16 );
return [r,g,b];
}
\ No newline at end of file
......@@ -8,6 +8,7 @@
<script src="js/Store.js"></script>
<script src="js/DOM.js"></script>
<script src="js/colors.js"></script>
<script src="js/Point.js"></script>
<style>
.collection-title {
font-family: 'Poppins', 'Montserrat', 'Lato', 'Roboto', 'Quicksand', sans-serif;
......@@ -65,7 +66,6 @@
.collection-title {
cursor: pointer;
}
.expanded .collection-title:before {
content: '+';
margin: 0 2px 0 0;
......@@ -171,8 +171,12 @@
right: 12px;
top: 0px;
font-family: monospace;
padding: 8px 10px;
padding: 5px 10px;
box-sizing: border-box;
cursor: pointer;
height: 100%;
font-size: 15px;
text-shadow: #000 0 0 2px;
}
.field {
......@@ -181,6 +185,115 @@
.block.hidden {
display: none;
}
.slider-background {
background: #104361;
height: 2px;
position: absolute;
left: 8px;
top: 7px;
right: 8px;
}
.slider {
position: relative;
height: 32px;
}
.slider-start {
position: absolute;
left:0;
}
.slider-start:before {
content: '';
height: 6px;
top: 5px;
left: 5px;
position: absolute;
background: #104361;
width: 6px;
border-radius: 50%;
z-index: 2;
}
.slider-end {
position: absolute;
right:0;
}
.slider-end:before {
content: '';
height: 6px;
top: 5px;
right: 5px;
position: absolute;
background: #104361;
width: 6px;
border-radius: 50%;
z-index: 2;
}
.slider-end__label {
position: absolute;
text-align: center;
left: 0;
font-family: Tahoma;
top: -3px;
}
.slider-start__label {
position: absolute;
text-align: center;
right: 4px;
font-family: Tahoma;
top: -3px;
}
.slider-drag {
width: 12px;
height: 12px;
margin-left: 2px;
top: 2px;
border: 2px solid #104361;
box-sizing: border-box;
cursor: pointer;
position: absolute;
z-index: 1;
border-radius: 50%;
background: #fff;
}
.grhm {
width: 50%;
left:25%;
position: relative;
}
.slider-zone {
position: absolute;
left: 8px;
right: 8px;
height: 8px;
top: 4px;
}
.slider-hover-val {
position: absolute;
top: -28px;
transform: translate(-40%);
font-family: Tahoma;
}
.sku-item {
margin: 8px 0;
cursor: pointer
}
span.sku-item-title {
position: relative;
bottom: 4px;
left: 8px;
font-family: 'Poppins', 'Montserrat', 'Lato', 'Roboto', 'Quicksand', sans-serif;
font-size: 18px;
}
.variant.byColor {
margin: 0 8px 0 8px;
}
.sku-item-distance {
left: 24px;
position: relative;
bottom: 4px;
font-family: monospace;
color: #49a;
}
</style>
</head>
<body>
......@@ -198,6 +311,56 @@
</script>
<script>
var Transform = (function() {
'use strict';
var hookAndConvert = function(fn) {
return function(hook, a) {
var type = typeof hook;
var notObject = type !== 'object';
var isHook = !notObject && ('hook' in hook);
if(isHook){
type = 'function'; notObject = true;
}
if(notObject){
if( type === 'function' ){
var last, val;
if(isHook){
return {hook: function(draw) {
return hook.hook(function(arg) {
val = fn(arg, a);
if(last === val)
return;
return draw(last = val);
});
}};
}else{
return function(draw) {
return hook(function(arg) {
val = fn(arg, a);
if(last === val)
return;
return draw(last = val);
});
};
}
}
}else{
return hook;
}
}
};
var Transform = {
toFixed: hookAndConvert(function(val, digits) {
return (val-0).toFixed(digits);
})
};
return Transform;
})();
window.T = Transform;
const slice = [].slice;
const Component = function( cfg ){
......@@ -305,6 +468,131 @@
Component.Property = {
Any: new Property( 'Any' )
};
var Slider = new Component({
ctor: function(cfg) {
Object.assign(this, cfg);
this.createDOM();
this.initBinding();
this.initEvents();
this.afterInit && this.afterInit();
},
prop: {
from: {type: Number},
to: {type: Number},
value: {type: Number, default: 0},
step: {type: Number, optional: true},
},
createDOM: function() {
this.dom = D.div({cls: 'slider'},
D.div({cls: 'slider-background'}),
this.zoneEl = D.div({cls: 'slider-zone'}),
D.div({cls: 'slider-start'},
D.div({cls: 'slider-start__label'}, T.toFixed(this.from,0) ),
),
D.div({cls: 'slider-end'},
D.div({cls: 'slider-end__label'}, T.toFixed(this.to, 0) )
),
this.dragEl = D.div({cls: 'slider-drag', style: {left: '0px'}})
);
this._updateUI = this._updateUI.bind(this);
this.afterDOM && this.afterDOM();
},
initEvents: function() {
var _self = this;
D.mouse.down(this.dom, function(e) {
var pos = new Point(e.clientX, e.clientY);
_self.getBound();
_self.calculateValue(pos);
_self.updateUI();
var update = D.AnimationFrame(function(pos) {
_self.calculateValue(pos);
_self.updateUI();
});
var un = D.mouse.move(document, function(e) {
e.preventDefault();
e.stopPropagation();
pos.x = e.clientX;
pos.y = e.clientY;
update(pos);
}, true);
D.overlay.show();
//un.add( D.mouse.up(_self.dom, un) );
un.add(function() {
D.overlay.hide();
});
un.add( D.mouse.up(window, un) );
});
},
getBound: function() {
var bound = this.zoneEl.getBoundingClientRect();
this.bound = {
left: bound.left,
top: bound.top,
height: bound.height,
width: bound.width
};
},
calculateValue: function(pos) {
var bound = this.bound;
var val = Math.min(Math.max(0, pos.x-bound.left), bound.width);
this.setValue(this.from.get()+(val/bound.width*(this.delta)));
},
afterAddToDOM: function() {
this.getBound();
this.updateUI();
},
bound: null,
_updateRequested: false,
_updateUI: function() {
this._updateRequested = false;
this.dragEl.style.left = (this.value.get()-this.from.get())/(this.delta)*this.bound.width+'px';
},
updateUI: function() {
if(this.bound){
if(!this._updateRequested){
this._updateRequested = true;
requestAnimationFrame(this._updateUI)
}
}
},
initBinding: function() {
var _self = this;
this.sub([this.value, this.from, this.to], function (val, from, to) {
_self.delta = to - from;
_self.setValue(val);
_self.updateUI();
});
},
lastValue: null,
setValue: function(val, silent) {
var inVal = val;
val = Math.min(this.to.get(), Math.max(this.from.get(), val));
if('step' in this){
var step = this.step.get();
val = Math.round(val/step)*step;
}
if(val !== this.lastValue || inVal !== val){
this.lastValue = val;
if(!silent) this.value.set(val);
}
}
});
var Radio = new Component( {
ctor: function(){
this.createDOM();
......@@ -385,7 +673,7 @@
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if( xmlhttp.readyState == 4 && xmlhttp.status == 200 ){
console.log( 'responseText:' + xmlhttp.responseText );
//console.log( 'responseText:' + xmlhttp.responseText );
try{
var data = JSON.parse( xmlhttp.responseText );
}catch( err ){
......@@ -401,14 +689,14 @@
}
var collections;
var debug = true;
var debug = false;
var rq = debug ? function( what, cfg, cb ){
getData( what, function( res ){
cb( res.collections.slice( -4 ) )
} );
} : function( what, cfg, cb ){
ajax_get( apiURL + URLS[ what ]( cfg ), function( res ){
cb( res.collections.reverse() );
cb( res.collections );
} )
};
......@@ -442,7 +730,7 @@
};
</script>
<div style="display: flex">
<div style="min-width: 460px;position: relative;display: flex;flex-direction: column;">
<div style="min-width: 460px;max-width: 460px;position: relative;display: flex;flex-direction: column;">
<div id='YMK-module' style="width:450px;position: relative;display: block"></div>
<div id="variant-info"></div>
</div>
......@@ -482,7 +770,8 @@
search: '',
categoriesLoaded: false,
searchColor: '#ff2f34',
searchFacePart: 'LIPCOLOR'
searchFacePart: 'LIPCOLOR',
threshold: 15
} );
var testIt = function( item, product, variant ){
//debugger
......@@ -546,6 +835,32 @@
}, 300 ) );
var nearItem = function(item) {
return D.div({cls: 'sku-item',
onclick: function(){
[].slice.apply( document.querySelectorAll( '.variant.selected' ) ).forEach( function( el ){
el.classList.remove( 'selected' );
} );
this.querySelector('.variant').classList.add( 'selected' );
YMK.applyMakeupBySku( item.val.sku );
}
},
D.div( {
cls: 'variant byColor',
style: { background: item.val.hex }
} ),
D.span( {
cls: 'sku-item-title'},
item.val.sku
),
D.span( {
cls: 'sku-item-distance'},
item.distance.toFixed(2)
)
)
};
var collection = function( item ){
return D.div( {
cls: D.cls( 'collection', {
......@@ -598,9 +913,8 @@
);
};
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');
var cats, cats2, grm, categories, cp = document.getElementById( 'content-panel' );
var cats, cats2, grm, categories, sld , cp = document.getElementById( 'content-panel' );
D.div( {
renderTo: cp
},
......@@ -633,7 +947,7 @@
onclick: function(){
s.set( 'search', '' )
}
}, 'x' ),
}, String.fromCharCode(10005) ),
new Input( { bind: s.bind( 'search' ) } )
),
......@@ -659,23 +973,47 @@
grm = D.div( { style: { position: 'relative' } },
D.div({style: {display: 'flex'}},
new Input( { bind: s.bind( 'searchColor' ) } ),
new Input( { bind: s.bind( 'searchColor' ), type: 'color' } ),
authorizeButton = D.h('Button', {}, 'Sign in'),
signoutButton = D.h('Button', {}, 'Sign out')
new Input( { bind: s.bind( 'searchColor' ), type: 'color' } )
)
),
categories = D.div({cls: 'search-categories'}),
D.div({style: {display: 'flex'}},
D.div({style: {'align-self': 'flex-end', 'padding-bottom': '16px'}}, 'Threshold:'),
D.div({style: {width: '100%', position: 'relative', padding: '32px 32px 0 32px'}},
sld = new Slider({from: 1, to: 40, value: s.bind('threshold'), step: 1, afterInit: function(){
D.div( { renderTo: this.dragEl, cls: 'slider-hover-val' }, T.toFixed( this.value, 0 ) );
}})
)
),
cats2 = D.div( { cls: 'categories' }, function( draw ){
s.sub( [ 'searchColor', 'skusLoaded' ], function( search, loaded ){
s.sub( [ 'searchColor', 'skusLoaded', 'threshold', 'searchFacePart' ], Store.debounce(function( searchColor, loaded, threshold, searchFacePart ){
if( loaded ){
var colorLab = XYZ2LAB.apply(null,(RGB2XYZ.apply(null,HEX2RGB(searchColor))));
draw(
values
.filter(function(val) {
return val.facePart === searchFacePart;
})
.map(function(val) {
return {distance: labDistance(val.lab, colorLab), val: val};
})
.filter(function(val) {
return val.distance<=threshold;
})
.sort(function(a, b) {
return a.distance - b.distance
})
.map(nearItem)
)
//draw( collections.map( collection ) );
}else{
draw( 'Loading collections' )
}
} )
}, 100) )
} )
)
);
......@@ -686,6 +1024,8 @@
});
var fn = function(){
sld.getBound();
sld._updateUI();
if(cats.offsetTop){
cp.style.minHeight = cats.style.height = Math.min( window.innerHeight + pageYOffset - ( cats.offsetTop + cats.offsetParent.offsetTop ) - 32, cats.scrollHeight, window.innerHeight - 32 ) + 'px';
}else if(cats2.offsetTop){
......@@ -694,98 +1034,33 @@
};
fn();
window.addEventListener( 'scroll', Store.debounce( fn, 300 ) );
s.sub( [ 'search', 'categoriesLoaded', 'searchColor', 'skusLoaded'], Store.debounce( fn, 300 ) );
s.sub( [ 'search', 'categoriesLoaded', 'searchColor', 'skusLoaded', 'searchType'], Store.debounce( fn, 300 ) );
setTimeout( fn, 1000 );
window.addEventListener( 'resize', fn );
function appendPre(message) {
var pre = grm;
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
// Client ID and API key from the Developer Console
var ACLIENT_ID = "838942638829-3koe535vg4adclpd01sd3nnmi250h2ra.apps.googleusercontent.com";
var AAPI_KEY = "AIzaSyD13Vbl1iq36HFABoVa27-VcOyqSMYNTZw";//"AIzaSyDx2DNm9fX9VXh6YzKEg5JybYSE6A6dZLg";
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/spreadsheets.readonly";
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listMajors();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function handleClientLoad() {
gapi.load('client:auth2', function initClient() {
gapi.client.init({
apiKey: AAPI_KEY,
clientId: ACLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
var values;
ajax_get('https://sheets.googleapis.com/v4/spreadsheets/1EkUKPUf2uedFd55lUj4_LQOb1EUXfcN8j96KU1qTy3w/values/SKU!A2:F?key=AIzaSyD13Vbl1iq36HFABoVa27-VcOyqSMYNTZw', function(res) {
values = res.values.map(function(arr) {
return {facePart: arr[0], sku: arr[1], hex: arr[2], lab: XYZ2LAB.apply(null,(RGB2XYZ.apply(null,HEX2RGB(arr[2])))) };
});
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
D.replaceChildren(categories, Object.keys(res.values.reduce(function(store, a) {
store[a[0]] = true;
return store;
}, {})).map(function(category) {
return D.h( 'label', { cls: 'field' },
new Radio( {
value: category,
group: s.bind( 'searchFacePart' )
} ),
category
);
}));
s.set('skusLoaded', true);
});
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
var values;
function listMajors() {
gapi.client.sheets.spreadsheets.values.get({
spreadsheetId: '1EkUKPUf2uedFd55lUj4_LQOb1EUXfcN8j96KU1qTy3w',
range: 'SKU!A2:F',
}).then(function(response) {
values = response.result.values;
D.replaceChildren(categories, Object.keys(values.reduce(function(store, a) {
store[a[0]] = true;
return store;
}, {})).map(function(category) {
return D.h( 'label', { cls: 'field' },
new Radio( {
value: category,
group: s.bind( 'searchFacePart' )
} ),
category
);
}));
s.set('skusLoaded', true);
}, function(response) {
appendPre('Error: ' + response.result.error.message);
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
\ No newline at end of file
{{ "Point.js" | asset_url | script_tag }}
{{ "Observer.js" | asset_url | script_tag }}
{{ "Store.js" | asset_url | script_tag }}
{{ "DOM.js" | asset_url | script_tag }}
<style>
.collection-title {
font-family: 'Poppins', 'Montserrat', 'Lato', 'Roboto', 'Quicksand', sans-serif;
font-size: 18px;
border-bottom: 2px solid;
margin: 4px;
display: inline-block;
padding: 2px 4px 0;
}
.products {
margin: 2px 8px;
font-family: 'Poppins', 'Montserrat', 'Lato', 'Roboto', 'Quicksand', sans-serif;
font-size: 14px;
}
.product {
margin: 4px 0;
}
.variant {
width: 24px;
height: 24px;
display: inline-block;
border-radius: 8px;
border: 1px solid #6b6a6a;
margin: 0 2px 0 0;
transition: all 0.3s ease-in;
}
.info .variant {
height: 80px;
min-width: 80px;
}
.variant.selected {
box-shadow: #5f5353 0px 0px 8px 2px;
border-color: #b5b5b5;
}
.variants {
margin: 4px 0 8px;
cursor: pointer
}
.collection.expanded .products {
display: none;
}
.collection-title:before {
content: '–';
margin: 0 2px 0 0;
}
.collection-title {
cursor: pointer;
}
.expanded .collection-title:before{
content: '+';
margin: 0 2px 0 0;
}
.info-line {
display: flex;
}
.very-info {
margin: 4px 8px;
width: 100%;
}
.info-title {
font-size: 24px;
margin: 32px 2px 8px;
}
.info {
font-family: 'Poppins', 'Montserrat', 'Lato', 'Roboto', 'Quicksand', sans-serif;
}
.info-img {
width: 80px;
}
input.field__input {
left: 0;
height: 32px;
position: relative;
padding: 4px;
width: calc(100% - 16px);
box-sizing: border-box;
margin: 0 4px;
}
.preview {
min-width: 96px;
}
span.color-span {
background: #fff;
padding: 4px 8px;
border-radius: 4px;
}
.color {
padding: 8px;
border-radius: 4px;
}
.info-description {
padding: 16px 0 0 16px;
}
span.prop:after {
content: ':';
}
span.prop {
color: #999;
padding: 0 8px 0 0;
font-size: 12px;
}
.categories {
position: absolute;
overflow-y: auto;
right: 12px;
left: 4px;
}
#content-panel {
width: 100%;
position: relative;
}
.variant.variant-hidden {
display: none;
}
.product.product-hidden {
display: none;
}
.collection.hidden {
display: none;
}
.product-counter {
padding-left: 10px;
color: #999;
}
.cross.hidden {
display: none;
}
.cross {
position: absolute;
z-index: 3;
right: 12px;
top: 0px;
font-family: monospace;
padding: 5px 10px;
box-sizing: border-box;
cursor: pointer;
height: 100%;
font-size: 15px;
text-shadow: #000 0 0 2px;
}
</style>
<div class="page-width page-content">
{%- include 'breadcrumbs' -%}
<div class="grid">
<div class="grid__item">
<div class="rte rte--nomargin">
<script>
const API_KEY = "SMB-Ojo6MjU1NDU=";
(function (d, k) {
var s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'https://plugins-media.perfectcorp.com/smb/sdk.js?apiKey=' + k;
var x = d.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})(document, API_KEY);
</script>
<script>
let YMK_close = document.getElementById('YMK-close');
let later = void 0;
function openTryOnTool() {
// If the product tags contain "Eyeshadow Palette", shows color swatches button, and make color swatches clickable.
let variant_div = document.getElementsByClassName("variant-input");
// Perfect Module
// if YMK is not inited - pass this problem to the future
if(!window.YMK || typeof YMK.open !== 'function'){
clearTimeout(later);
return later = setTimeout(openTryOnTool, 300);
}else{
if(!YMK.autoShow){
YMK.autoShow = true;
YMK.addEventListener('loaded', function(){console.log('after YMK loaded');
// set current active variant
YMK.applyMakeupBySku(document.querySelector('.variant-input-wrap input:checked').parentNode.getAttribute('perfect_sku_id'));
});
}
}
YMK.open()
let YMK_module = document.getElementById('YMK-module');
const YMK_SCREEN = "ymk-screen"
if (YMK.open()) {
YMK_module.classList.add(YMK_SCREEN)
//YMK_close.style.color = "black";
} else {
YMK_module.classList.remove(YMK_SCREEN)
}
}
function closeTryOnTool() {
YMK.close()
YMK.close() ? YMK_close.style.color = "transparent" : YMK_close.style.color = "black";
}
function ajax_get(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//console.log('responseText:' + xmlhttp.responseText);
try {
var data = JSON.parse(xmlhttp.responseText);
} catch(err) {
console.log(err.message + " in " + xmlhttp.responseText);
return;
}
callback(data);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
var collections;
var debug = false;
var rq = debug ? function(what,cfg, cb) {
getData(what, function(res){
cb(res.collections.slice(-4))
});
} : function(what,cfg, cb) {
ajax_get(apiURL+URLS[what](cfg), function(res) {
cb(res.collections);
})
};
var loaded = {};
var collectionRQ = debug ? function(what,cfg, cb) {
getData(cfg.handle.substr(3).replace('-results', ''), function(res){
cb(res.products)
});
} : function(what,cfg, cb) {
ajax_get(apiURL+URLS[what](cfg), function(res) {
cb(res.products);
})
};
var loadingSequence = function() {
rq('collections', null, function(data) {
collections = data;
s.set('categoriesLoaded', 1);
collections.forEach(function(item) {
collectionRQ('category', item, function(products) {
loaded[item.handle] = products;
s.set(item.handle+'-loaded', true);
s.set('categoriesLoaded', s.get('categoriesLoaded')+1);
s.set(item.handle + '-notcollapsed', true);
})
});
})
};
</script>
<div style="display: flex">
<div style="min-width: 460px;max-width: 460px;position: relative;display: flex;flex-direction: column;">
<div id='YMK-module' style="width:450px;position: relative;display: block"></div>
<div id="variant-info"></div>
</div>
<div id="content-panel">
</div>
</div>
<script>
openTryOnTool();
var apiURL = 'https://www.mirrormirror.love/';
var URLS = {
collections: function(){return 'collections.json';},
category: function(item){
return `collections/${item.handle}/products.json?limit=250?page=1`;
}
};
loadingSequence();
var Input = function(cfg){
var dom = D.h('input', {cls:"field__input", attr: {type: 'text'}});
if(cfg.bind){
cfg.bind.sub(function (val) {
dom.value = val;
});
dom.addEventListener('input', function () {
cfg.bind.set(dom.value);
})
}
return dom;
};
var s = new Store({
search: '',
categoriesLoaded: false
});
var testIt = function(item, product, variant){
//debugger
var img = variant.featured_image && variant.featured_image.src || ( product.images[ 0 ] || {} ).src;
console.log( { item, product, variant } );
D.replaceChildren(
document.querySelector( '#variant-info' ),
D.div( { cls: 'info' },
D.div( { cls: 'info-title' }, product.title ),
D.div( { cls: 'info-line' },
D.div({cls: 'preview'},
img && D.h('img', {src: img, cls: 'info-img'})
),
D.div({cls: 'very-info'},
D.div({cls: 'color', style: {background: variant.option2}}, D.span({cls: 'color-span'}, D.span({cls: 'prop'},'Color'), variant.option1)),
'SKU: '+variant.option3
)
),
D.div({cls: 'info-description'}, function(draw) {
var d = D.div({});
d.innerHTML = product.body_html;
draw(d);
})
)
);
YMK.applyMakeupBySku(variant.option3);
};
s.sub( [ 'search', 'categoriesLoaded' ], Store.debounce( function( search, isLoaded ){
if( !isLoaded )
return;
search = search.toLowerCase().trim();
collections.forEach( function( collection ){
var products = loaded[ collection.handle ];
if( products ){
var filteredProducts = products.filter( function( product ){
var filteredVariants = product.variants.filter( function( variant ){
var shouldShow = variant.option3 &&
( search ?
variant.option3.toLowerCase().indexOf( search ) > -1
: true );
s.set( 'v' + variant.id + '-hidden', !shouldShow );
return shouldShow;
} );
s.set( 'p' + product.id + '-hidden', filteredVariants.length === 0 );
return filteredVariants.length > 0;
} );
s.set( collection.handle + '-count', filteredProducts.length );
s.set( collection.handle + '-hide', filteredProducts.length === 0 );
}else{
s.set( collection.handle + '-hide', true );
}
} )
}, 300 ) );
var collection = function( item ){
return D.div( {
cls: D.cls( 'collection', {
hidden: s.valTrue( item.handle + '-hide' ),
expanded: s.valTrue( item.handle + '-notcollapsed' )
} )
},
D.div( {
cls: 'collection-title',
onclick: function(){
s.set( item.handle + '-notcollapsed', !( s.get( item.handle + '-notcollapsed' ) ) );
}
}, item.title, D.span( { cls: 'product-counter' }, s.val( item.handle + '-count' ) ) ),
function( draw ){
s.sub( [ item.handle + '-loaded' ], function( isLoaded ){
if( !isLoaded )
return;
var products = loaded[ item.handle ];
var mapped = products.map( function( product ){
return D.div( { cls: D.cls( 'product', { 'product-hidden': s.valTrue( 'p' + product.id + '-hidden' ) } ) },
D.div( { cls: 'product-title' }, product.title ),
D.div( { cls: 'variants' }, product.variants.map( function( variant ){
return D.div( {
cls: D.cls( 'variant', { 'variant-hidden': s.valTrue( 'v' + variant.id + '-hidden' ) } ),
style: { background: variant.option2 },
onclick: function(){
[].slice.apply( document.querySelectorAll( '.variant.selected' ) ).forEach( function( el ){
el.classList.remove( 'selected' );
} );
this.classList.add( 'selected' );
testIt( item, product, variant )
}
} )
} ) )
)
} )
.filter( function( a ){
return a;
} );
s.set( item.handle + '-hide', mapped.length === 0 );
draw( D.div( { cls: 'products' }, mapped ) );
} );
}
);
};
var cats, cp = document.getElementById( 'content-panel' );
D.div( {
renderTo: cp
},
D.div( { style: { position: 'relative' } },
D.div( {
cls: D.cls( 'cross', { hidden: s.valEqual( 'search', '' ) } ),
onclick: function(){
s.set( 'search', '' )
}
}, String.fromCharCode(10005) ),
new Input( { bind: s.bind( 'search' ) } )
),
cats = D.div( { cls: 'categories' }, function( draw ){
s.sub( [ 'search', 'categoriesLoaded' ], function( search, loaded ){
if( loaded ){
draw( collections.map( collection ) );
}else{
draw( 'Loading collections' )
}
} )
} )
);
var fn = function(){
cp.style.minHeight = cats.style.height = Math.min(window.innerHeight + pageYOffset - (cats.offsetTop + cats.offsetParent.offsetTop) - 32, cats.scrollHeight, window.innerHeight-32) +'px';
};
fn();
window.addEventListener('scroll', Store.debounce(fn,300));
s.sub([ 'search', 'categoriesLoaded' ], Store.debounce(fn,300));
setTimeout(fn, 1000);
window.addEventListener('resize', fn);
</script>
</div>
</div>
</div>
</div>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment