Commit 6ac370f0 by Иван Кубота

add color sort props in all page

parent 29bb3e9a
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebResourcesPaths">
<contentEntries>
<entry url="file://$PROJECT_DIR$">
<entryData>
<resourceRoots>
<path value="file://$PROJECT_DIR$/examples/examples-browser/public" />
</resourceRoots>
</entryData>
</entry>
</contentEntries>
</component>
</project>
\ No newline at end of file
var Observable = function() {
this._clearListeners();
};
Observable.prototype = {
on: function(k, v) {
(this._listeners[k] || (this._listeners[k] = [])).push(v);
var _self = this;
return function ReleaseObservable() {
_self.un(k, v);
};
},
un: function(k, v) {
var list = this._listeners[k];
if(list){
var id = list.indexOf(v);
if(id > -1){
list.splice(id, 1);
}
}
},
fire: function(k) {
var listeners = this._listeners[k],
listener;
if(listeners === void 0)
return;
for( var i = 0, _i = listeners.length; i < _i; i++ ){
listener = listeners[ i ];
if(listener) {
listener.apply(this, [].slice.call(arguments, 1));
}
}
},
once: function(k, v) {
var _self = this,
wrap = function() {
v.apply(this, arguments);
_self.un(k, wrap)
};
this.on(k, wrap);
},
_clearListeners: function() {
this._listeners = {};
}
};
typeof module === 'object' && (module.exports = Observable);
\ No newline at end of file
const isEqual = function(original, fn) {
return function(val) {
fn(val===original);
}
};
const isContain = function(original, fn) {
return function(val) {
fn((val||[]).indexOf(original)>-1);
}
};
const Store = function(cfg) {
Observable.call(this);
this.events = new Observable();
this._props = cfg || {};
},
isObject = function(obj) {
// null is not an object. treat Date as primitive
return typeof obj === 'object' && obj !== null && !(obj instanceof Date);
};
const recursiveWalk = function(path, pointer, key, list) {
if(typeof pointer[key] === 'object'){
for(let subKey in pointer[key]){
if(typeof pointer[key][subKey] === 'object'){
list.push( [ path.concat( key, subKey ).join('.'), void 0 ] );
}
recursiveWalk(path.concat(key), pointer[key], subKey, list);
}
}else{
list.push( [ path.concat( key ).join('.'), void 0 ] );
}
},
recursiveSet = function(path, pointer, key, val, list){
let subKey,i, originalLength;
if( isObject(val) ){
if(Array.isArray(val)){
if(!Array.isArray(pointer[key])){
pointer[ key ] = [];
list.push([path.concat(key).join( '.' ), pointer[ key ]])
}
originalLength = pointer[ key ].length;
}else{
if(!isObject(pointer[ key ])){
pointer[ key ] = {};
list.push([path.concat(key).join( '.' ), pointer[ key ]])
}
}
for(subKey in val){
recursiveSet( path.concat( key ), pointer[ key ], subKey, val[subKey], list );
}
for( subKey in pointer[ key ] ){
if( !val.hasOwnProperty( subKey ) ){
// remove
recursiveWalk( path.concat( key ), pointer[key], subKey, list );
delete pointer[ key ][ subKey ];
}
}
if(Array.isArray(val)){
if(originalLength !== val.length){
recursiveSet( path.concat( key ), pointer[ key ], 'length', val.length, list );
list.push([path.concat(key).join( '.' ), pointer[ key ]]);
}
}
}else{
if( val !== pointer[ key ] ){
pointer[ key ] = val;
list.push( [ path.concat(key).join( '.' ), pointer[ key ] ] );
}
}
};
var StoreParent = function(parent, key, item) {
this.parent = parent;
this.key = key;
this.item = item;
};
StoreParent.prototype = {
getKey: function() {
if(this.item){
var idx = this.parent._props.indexOf(this.item);
if(idx > -1)
return idx;
console.error('try to write to not existed item');
}else{
return this.key;
}
}
};
Store.prototype = {
parent: null,
setParent: function(parent, key, item){
this.parent = new StoreParent(parent, key, item);
},
item: function(key, item){
let subStore = new Store(item?item:key);
subStore.setParent(this, key, item);
return subStore;
},
array: function(key){
let arrayStore = new ArrayStore(this.get(key))
arrayStore.setParent(this, key)
return arrayStore;
},
experimental: false,
_set: function(keys, val, pointer, changeList) {
changeList = changeList || [];
let parent, i, _i;
for(i=0, _i = keys.length - 1; i < _i; i++){
let key = keys[i];
parent = pointer;
if(key in pointer){
pointer = parent[key];
if(!isObject(pointer)){
pointer = parent[key] = {};
changeList.push([keys.slice(0, i).join( '.' ), parent[key]]);
}
}else{
pointer = parent[key] = {};
changeList.push([keys.slice(0, i+1).join( '.' ), parent[key]]);
}
}
let key = keys[i];
recursiveSet(keys.slice(0, keys.length - 1), pointer, key, val, changeList);
},
clear: function() {
this._props = {};
this.events.fire('change', null, null);
},
/*
key: String, val: any
key: {k: v, ...}
*/
set: function(key, val, changeList) {
var isChangeList = changeList !== void 0;
changeList = changeList || [];
var type = typeof key;
if(type === 'object'){
for(let k in key){
this.set(k, key[k], changeList);
}
this._notify(changeList);
return this;
}
var _key;
if(type === 'string') {
_key = key.split('.');
}else if(type === 'number'){
_key = [key];
}
this._set(
_key,
val,
this._props,
changeList
);
if(!isChangeList)
this._notify(changeList);
return this;
},
reSet: function(key, val, changeList) {
this._props = {};
if(key===void 0)
return this;
return this.set(key, val, changeList);
},
_notify: function(changeList, prefix) {
prefix = prefix || '';
for( let i = changeList.length; i; ){
const changeListElement = changeList[ --i ];
var key = changeListElement[0], val = changeListElement[1],
fullKey = prefix+(key===''?'':(prefix===''?'':'.')+key);
this.events.fire('change', fullKey, changeListElement[1]);
this.fire(fullKey, changeListElement[1]);
}
if(this.parent){
if(prefix) {
this.parent.parent._notify(changeList, this.parent.getKey() + '.' + prefix);
}else{
this.parent.parent._notify(changeList, this.parent.getKey());
}
}
},
get: function(key, returnLastStore) {
if(key === void 0)
return this._props;
let type = typeof key;
if(type === 'string') {
key = key.split('.');
}
if(type === 'number') {
key = [key];
}
let ref = this,
lastStore = ref, i, _i;
for( i = 0, _i = key.length; i < _i; i++ ){
if( ref instanceof Store ){
ref = ref._props[key[i]];
lastStore = ref;
}else{
ref = ref[key[i]];
}
if( !ref && i < key.length - 1 )
return void 0;
}
if( returnLastStore )
return { lastQObject: lastStore, result: ref };
return ref;
},
sub: function(key, fn, suppresFirstCall) {
var un;
if(Array.isArray(key)){
var wrap = () => fn.apply(this, key.map(key=>key instanceof StoreBinding ? key.get() : this.get(key)));
var uns = [];
for( var i = 0, _i = key.length; i < _i; i++ ){
if(key[i] instanceof StoreBinding){
uns.push(key[i].sub(wrap));
}else{
uns.push(this.on( key[ i ], wrap ))
}
}
!suppresFirstCall && wrap();
return function() {
for( var i = 0, _i = uns.length; i < _i; i++ ){
uns[ i ]();
}
};
}else{
un = this.on( key, fn );
!suppresFirstCall && fn( this.get( key ) );
return un;
}
},
equal: function(key, val, fn) {
const wrap = isEqual(val, fn);
this.on(key, wrap);
wrap(this.get(key));
return this;
},
contain: function(key, val, fn) {
const wrap = isContain(val, fn);
this.on(key, wrap);
wrap(this.get(key));
return this;
},
bind: function (key) {
return new StoreBinding(this, key);
},
val: function(key) {
const me = this;
return function backwardCallback(update) {
me.sub(key, val => update(val));
}
},
valEqual: function(key, val) {
const me = this;
return function backwardCallback(update) {
me.equal(key, val, compareResult => {update(compareResult)});
}
},
valEqualOnly: function(key, val) {
const me = this;
return function backwardCallback(update) {
me.equal(key, val, compareResult => {compareResult && update(compareResult)});
}
},
valContains: function(key, val) {
const me = this;
return function backwardCallback(update) {
me.contain(key, val, compareResult => {compareResult && update(compareResult)});
}
},
valTrue: function(key) {
return this.valEqual(key, true);
},
valFalse: function(key) {
return this.valEqual(key, false);
}
};
const StoreBinding = function(store, key){
this.store = store;
this.key = key;
};
StoreBinding.prototype = {
sub: function (k, fn) {
if(typeof k === 'function'){
fn = k;
return this.un = this.store.sub(this.key, fn);
}else{
return this.un = this.store.sub(
(Array.isArray(k)?k:[k]).map(k=>this.key+'.'+k), fn);
}
},
set: function (val) {
this.store.set(this.key, val);
},
get: function() {
return this.store.get(this.key);
},
bind: function(key) {
return new StoreBinding(this.store, this.key+'.'+key);
}
};
Store.prototype = Object.assign(new Observable, Store.prototype);
Store.StoreBinding = StoreBinding;
Store.AGGREGATE = function(fn) {
return function(...args) {
let composite, _i = args.length,
vals = new Array(_i);
return function(update) {
let check = ()=>{
let result = fn(vals, _i);
if(composite !== result)
update(composite = result);
};
for(let i = 0; i < _i; i++){
// set backward callback
let hook = val => {
// update item corresponding value and check condition
vals[ i ] = val;
check();
};
if(args[i] instanceof HookPrototype){
args[i].hook(hook)
}else{
args[ i ]( hook )
}
}
};
};
};
Store.AND = Store.AGGREGATE(function(values, length) {
let result = true;
for(let i = 0; i < length; i++){
result = result && values[i];
}
return result;
});
Store.OR = Store.AGGREGATE(function(values, length) {
let result = false;
for(let i = 0; i < length; i++){
result = result || values[i];
}
return result;
});
Store.ELSE = function(){if(!( this instanceof Store.ELSE))return new Store.ELSE()};
Store.IF = function(cfg, children){
var holders = {true: [], false: []},
holder = holders.true;
for( var i = 0, _i = children.length; i < _i; i++ ){
var child = children[ i ];
if(child instanceof Store.ELSE){
holder = holders.false;
}else{
holder.push(child);
}
}
holders.true.length === 0 && (holders.true = null);
holders.false.length === 0 && (holders.false = null);
return function( update ){
if( 'condition' in cfg )
var hook = function( cond ){
update( cond ? holders.true : holders.false );
};
if(cfg.condition instanceof HookPrototype){
cfg.condition.hook( hook );
}else if(typeof cfg.condition === 'function'){
cfg.condition( hook );
}else{
// TODO other hooklikes
hook(cfg.condition)
}
}
};
Store.NOT = Store.AGGREGATE(function(values, length) {
return !values[0];
});
Store.debounce = function(fn, dt) {
var timeout = false, args, scope,
realCall = function() {
timeout = false;
fn.apply(scope, args)
};
return function(){
args = [].slice.call(arguments);
scope = this;
if(!timeout){
timeout = setTimeout(realCall, dt);
}
}
};
var HookPrototype = function() {};
HookPrototype.prototype = {
setter: function(val) { return val; },
//getter: function(val) { return val; },
set: function(val) {
val = this.setter(val);
var oldVal = this.get();
if(!this.equal(oldVal, val)){
this.data = val;
this._emit(oldVal, val);
}
},
equal: function(oldVal, newVal){
return newVal === oldVal;
},
get: function() {
return this.data;
},
binding: function() {
var x = new StoreBinding();
x.get = ()=> this.get();
x.set = (a)=> this.set(a);
x.sub = (fn)=> this.hook(fn);
return x;
},
hook: function(fn) { this.subscribers.push(fn); fn(this.get()); },
_emit: function(oldVal, val) {
var subscribers = this.subscribers;
for( var i = 0, _i = subscribers.length; i < _i; i++ ){
subscribers[ i ](val);
}
}
};
var HookFactory = function(accessor) {
var Hook = function(cfg) {
if(!(this instanceof Hook))
return new Hook(cfg);
this.data = {};
this.subscribers = [];
this.set(cfg);
};
Hook.prototype = Object.assign( new HookPrototype(), accessor );
return Hook;
};
Store.Value = {
Boolean: new HookFactory({
setter: function(val) { return !!val; },
toggle: function() { this.set(!this.get()); }
}),
Number: new HookFactory({
setter: function(val) { return val|0; }
})
};
Store.HookPrototype = HookPrototype;
const ArrayStore = function (cfg) {
Store.call(this, cfg);
};
ArrayStore.prototype = {
push: function (val) {
var changeList = [];
changeList.push(['', this._props])
this.set(this.getLength(), val, changeList);
this._notify(changeList);
return this;
},
pop: function () {
var changeList = [];
changeList.push(['', this._props]);
var out = this.get(this.getLength()-1);
this.set(this.getLength()-1, void 0, changeList);
this._props.pop();
this._notify(changeList);
return out;
},
remove: function(item) {
var idx = this._props.indexOf(item);
if(idx>-1){
var changeList = [];
changeList.push(['', this._props]);
this._props.splice(idx,1);
//this.set(this.getLength()-1, void 0, changeList);
this._notify(changeList);
}
return this;
},
slice: function () {},
splice: function () {},
getLength: function () {
return this._props.length;
},
update: function() {
var changeList = [];
changeList.push(['', this._props]);
this._notify(changeList);
return this;
},
'~destructor': function() {
this._listeners = this.events = this._props = null;
}
};
ArrayStore.prototype = Object.assign(new Store(), ArrayStore.prototype);
typeof module === 'object' && (module.exports = Store);
(typeof window === 'object') && (window.Store = Store);
\ No newline at end of file
...@@ -7,7 +7,20 @@ ...@@ -7,7 +7,20 @@
<script src="js/extract-colors.js"></script> <script src="js/extract-colors.js"></script>
<script src="js/data.js"></script> <script src="js/data.js"></script>
<script src="js/DOM.js"></script> <script src="js/DOM.js"></script>
<script src="js/Observer.js"></script>
<script src="js/Store.js"></script>
<style> <style>
label {
display: block;
}
input.field__input {
position: absolute;
left: 128px;
width: 4em;
border: 0;
border-bottom: 1px solid #999;
text-align: center;
}
body { body {
margin: 16px; margin: 16px;
padding: 0; padding: 0;
...@@ -78,8 +91,28 @@ ...@@ -78,8 +91,28 @@
</head> </head>
<body> <body>
<script> <script>
var store = window.store = new Store({
h: 50,
s: 35,
v: 0
});
var list = ['brows','lips','blush','eyes']; var list = ['brows','lips','blush','eyes'];
var lastEl; var lastEl;
var Input = function(cfg){
var dom = D.h('input', {cls:"field__input", attr: {type: 'number'}});
if(cfg.bind){
cfg.bind.sub(function (val) {
dom.value = val;
});
dom.addEventListener('input', function () {
cfg.bind.set(dom.value);
})
}
return dom;
};
var preview = function(item, el) { var preview = function(item, el) {
lastEl && lastEl.classList.remove('active'); lastEl && lastEl.classList.remove('active');
lastEl && (lastEl.childNodes[0].style.borderColor = '#fff'); lastEl && (lastEl.childNodes[0].style.borderColor = '#fff');
...@@ -111,41 +144,63 @@ ...@@ -111,41 +144,63 @@
}, updateRight; }, updateRight;
D.div({cls: 'viewport', renderTo: document.body}, D.div({cls: 'viewport', renderTo: document.body},
D.div({cls: 'left'}, D.div({cls: 'left'},
D.div({cls: 'block'},
D.div({cls: 'title'},'Color sort:'),
D.h('label', {},
'Hue: ', D.h(Input, {bind: store.bind('h')})
),
D.h('label', {},
'Saturation: ', D.h(Input, {bind: store.bind('s')})
),
D.h('label', {},
'Value: ', D.h(Input, {bind: store.bind('v')})
)
),
list.map(function(name) { list.map(function(name) {
return D.div({cls: 'block'}, return D.div({cls: 'block'},
D.div({cls: 'title'}, name[0].toUpperCase()+name.substr(1)), D.div({cls: 'title'}, name[0].toUpperCase()+name.substr(1)),
(draw)=>{ (draw)=>{
getData(name, function(res) { getData(name, function(res) {
var list = [];
res.products.forEach(function(product) {
product.variants.forEach(function(variant) {
var color = variant.option2.substr(1),
r = parseInt(color[0]+color[1], 16),
g = parseInt(color[2]+color[3], 16),
b = parseInt(color[4]+color[4], 16);
list.push({ store.sub(['h','s','v'], function(h,s,v){
pid: product.id,
vid: variant.id,
description: product.body_html,
title: product.title,
color: variant.option2,
colorName: variant.option1,
img: variant.featured_image && variant.featured_image.src || (product.images[0] || {}).src,
sku: variant.option3,
hsv: rgbToHsv(r,g,b)
});
});
});
list.sort(function(a,b) {
return (a.hsv[0]-b.hsv[0])*10+(b.hsv[2]-a.hsv[2])/2+(a.hsv[1]-b.hsv[1])/2;
});
draw(list.map(function(item) {
return D.div({attr: {'data-id': item.pid}, cls: 'row', onClick: function(){preview(item, this)}},
D.div({cls: 'cp', style: {background: item.color}})
)
}))
var list = [];
res.products.forEach( function( product ){
product.variants.forEach( function( variant ){
var color = variant.option2.substr( 1 ),
r = parseInt( color[ 0 ] + color[ 1 ], 16 ),
g = parseInt( color[ 2 ] + color[ 3 ], 16 ),
b = parseInt( color[ 4 ] + color[ 4 ], 16 );
list.push( {
pid: product.id,
vid: variant.id,
description: product.body_html,
title: product.title,
color: variant.option2,
colorName: variant.option1,
img: variant.featured_image && variant.featured_image.src || ( product.images[ 0 ] || {} ).src,
sku: variant.option3,
hsv: rgbToHsv( r, g, b )
} );
} );
} );
list.sort( function( a, b ){
return ( a.hsv[ 0 ] - b.hsv[ 0 ] ) * h + ( b.hsv[ 2 ] - a.hsv[ 2 ] ) * s + ( a.hsv[ 1 ] - b.hsv[ 1 ] ) * v;
} );
draw( list.map( function( item ){
return D.div( {
attr: { 'data-id': item.pid }, cls: 'row', onClick: function(){
preview( item, this )
}
},
D.div( { cls: 'cp', style: { background: item.color } } )
)
} ) )
});
}); });
} }
) )
......
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