Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging
This commit is contained in:
commit
a13261abaa
@ -12,5 +12,24 @@ define(function() {
|
|||||||
*/
|
*/
|
||||||
config.notificationTimeout = 5000;
|
config.notificationTimeout = 5000;
|
||||||
|
|
||||||
|
config.whiteboardPalette = [
|
||||||
|
'#000000', // black
|
||||||
|
'#FFFFFF', // white
|
||||||
|
'#848484', // grey
|
||||||
|
'#8B4513', // saddlebrown
|
||||||
|
'#FF0000', // red
|
||||||
|
'#FF8080', // peach?
|
||||||
|
'#FF8000', // orange
|
||||||
|
'#FFFF00', // yellow
|
||||||
|
'#80FF80', // light green
|
||||||
|
'#00FF00', // green
|
||||||
|
'#00FFFF', // cyan
|
||||||
|
'#008B8B', // dark cyan
|
||||||
|
'#0000FF', // blue
|
||||||
|
'#FF00FF', // fuschia
|
||||||
|
'#FF00C0', // hot pink
|
||||||
|
'#800080', // purple
|
||||||
|
];
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
|
|||||||
138
rpc.js
138
rpc.js
@ -122,23 +122,6 @@ var checkSignature = function (signedMsg, signature, publicKey) {
|
|||||||
return Nacl.sign.detached.verify(signedBuffer, signatureBuffer, pubBuffer);
|
return Nacl.sign.detached.verify(signedBuffer, signatureBuffer, pubBuffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
var storeMessage = function (store, publicKey, msg, cb) {
|
|
||||||
store.message(publicKey, JSON.stringify(msg), cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var pinChannel = function (store, publicKey, channel, cb) {
|
|
||||||
store.message(publicKey, JSON.stringify(['PIN', channel]), cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var unpinChannel = function (store, publicKey, channel, cb) {
|
|
||||||
store.message(publicKey, JSON.stringify(['UNPIN', channel]), cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var resetUserPins = function (store, publicKey, channelList, cb) {
|
|
||||||
// TODO make this atomic
|
|
||||||
store.message(publicKey, JSON.stringify(['RESET']), cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var getChannelList = function (store, publicKey, cb) {
|
var getChannelList = function (store, publicKey, cb) {
|
||||||
// to accumulate pinned channels
|
// to accumulate pinned channels
|
||||||
var pins = {};
|
var pins = {};
|
||||||
@ -160,6 +143,17 @@ var getChannelList = function (store, publicKey, cb) {
|
|||||||
Object.keys(pins).forEach(function (pin) {
|
Object.keys(pins).forEach(function (pin) {
|
||||||
pins[pin] = false;
|
pins[pin] = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!parsed[1] || parsed[1].length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parsed[1].forEach(function (channel) {
|
||||||
|
pins[channel] = true;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('invalid message read from store');
|
console.error('invalid message read from store');
|
||||||
@ -178,6 +172,34 @@ var getChannelList = function (store, publicKey, cb) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var getFileSize = function (store, channel, cb) {
|
||||||
|
if (!isValidChannel(channel)) { return void cb('INVALID_CHAN'); }
|
||||||
|
|
||||||
|
return void store.getChannelSize(channel, function (e, size) {
|
||||||
|
if (e) { return void cb(e.code); }
|
||||||
|
cb(void 0, size);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var getTotalSize = function (pinStore, messageStore, publicKey, cb) {
|
||||||
|
var bytes = 0;
|
||||||
|
|
||||||
|
return void getChannelList(pinStore, publicKey, function (channels) {
|
||||||
|
if (!channels) { cb('NO_ARRAY'); } // unexpected
|
||||||
|
|
||||||
|
var count = channels.length;
|
||||||
|
if (!count) { cb(void 0, 0); }
|
||||||
|
|
||||||
|
channels.forEach(function (channel) {
|
||||||
|
return messageStore.getChannelSize(channel, function (e, size) {
|
||||||
|
count--;
|
||||||
|
if (!e) { bytes += size; }
|
||||||
|
if (count === 0) { return cb(void 0, bytes); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var hashChannelList = function (A) {
|
var hashChannelList = function (A) {
|
||||||
var uniques = [];
|
var uniques = [];
|
||||||
|
|
||||||
@ -194,7 +216,44 @@ var hashChannelList = function (A) {
|
|||||||
|
|
||||||
var getHash = function (store, publicKey, cb) {
|
var getHash = function (store, publicKey, cb) {
|
||||||
getChannelList(store, publicKey, function (channels) {
|
getChannelList(store, publicKey, function (channels) {
|
||||||
cb(hashChannelList(channels));
|
cb(void 0, hashChannelList(channels));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var storeMessage = function (store, publicKey, msg, cb) {
|
||||||
|
store.message(publicKey, JSON.stringify(msg), cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
var pinChannel = function (store, publicKey, channel, cb) {
|
||||||
|
store.message(publicKey, JSON.stringify(['PIN', channel]),
|
||||||
|
function (e) {
|
||||||
|
if (e) { return void cb(e); }
|
||||||
|
|
||||||
|
getHash(store, publicKey, function (e, hash) {
|
||||||
|
cb(e, hash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var unpinChannel = function (store, publicKey, channel, cb) {
|
||||||
|
store.message(publicKey, JSON.stringify(['UNPIN', channel]),
|
||||||
|
function (e) {
|
||||||
|
if (e) { return void cb(e); }
|
||||||
|
|
||||||
|
getHash(store, publicKey, function (e, hash) {
|
||||||
|
cb(e, hash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetUserPins = function (store, publicKey, channelList, cb) {
|
||||||
|
store.message(publicKey, JSON.stringify(['RESET', channelList]),
|
||||||
|
function (e) {
|
||||||
|
if (e) { return void cb(e); }
|
||||||
|
|
||||||
|
getHash(store, publicKey, function (e, hash) {
|
||||||
|
cb(e, hash);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -282,45 +341,30 @@ RPC.create = function (config, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (msg[0]) {
|
switch (msg[0]) {
|
||||||
case 'COOKIE':
|
case 'COOKIE': return void Respond(void 0);
|
||||||
return void Respond(void 0);
|
|
||||||
case 'ECHO':
|
|
||||||
return void Respond(void 0, msg);
|
|
||||||
|
|
||||||
/* TODO
|
|
||||||
reset should be atomic in case the operation is aborted */
|
|
||||||
case 'RESET':
|
case 'RESET':
|
||||||
return resetUserPins(store, safeKey, [], function (e) {
|
return resetUserPins(store, safeKey, msg[1], function (e, hash) {
|
||||||
return void Respond(e);
|
return void Respond(e, hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/* TODO
|
|
||||||
pin and unpin operations should respond with the new hash */
|
|
||||||
case 'PIN':
|
case 'PIN':
|
||||||
return pinChannel(store, safeKey, msg[1], function (e) {
|
return pinChannel(store, safeKey, msg[1], function (e, hash) {
|
||||||
Respond(e);
|
Respond(e, hash);
|
||||||
});
|
});
|
||||||
case 'UNPIN':
|
case 'UNPIN':
|
||||||
return unpinChannel(store, safeKey, msg[1], function (e) {
|
return unpinChannel(store, safeKey, msg[1], function (e, hash) {
|
||||||
Respond(e);
|
Respond(e, hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
case 'GET_HASH':
|
case 'GET_HASH':
|
||||||
return void getHash(store, safeKey, function (hash) {
|
return void getHash(store, safeKey, function (e, hash) {
|
||||||
Respond(void 0, hash);
|
Respond(e, hash);
|
||||||
});
|
});
|
||||||
case 'GET_TOTAL_SIZE':
|
case 'GET_TOTAL_SIZE':
|
||||||
return void Respond('NOT_IMPLEMENTED', msg);
|
return getTotalSize(store, ctx.store, safeKey, function (e, size) {
|
||||||
case 'GET_FILE_SIZE':
|
if (e) { return void Respond(e); }
|
||||||
if (!isValidChannel(msg[1])) {
|
Respond(e, size);
|
||||||
return void Respond('INVALID_CHAN');
|
|
||||||
}
|
|
||||||
|
|
||||||
return void ctx.store.getChannelSize(msg[1], function (e, size) {
|
|
||||||
if (e) { return void Respond(e.code); }
|
|
||||||
Respond(void 0, size);
|
|
||||||
});
|
});
|
||||||
|
case 'GET_FILE_SIZE':
|
||||||
|
return void getFileSize(ctx.store, msg[1], Respond);
|
||||||
default:
|
default:
|
||||||
return void Respond('UNSUPPORTED_RPC_CALL', msg);
|
return void Respond('UNSUPPORTED_RPC_CALL', msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,34 +28,8 @@ define([
|
|||||||
rpc.send('GET_FILE_SIZE', file, cb);
|
rpc.send('GET_FILE_SIZE', file, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
var getFileListSize = function (rpc, list, cb) {
|
var getFileListSize = function (rpc, cb) {
|
||||||
var bytes = 0;
|
return rpc.send('GET_TOTAL_SIZE', undefined, cb);
|
||||||
|
|
||||||
var left = list.length;
|
|
||||||
|
|
||||||
list.forEach(function (chan) {
|
|
||||||
getFileSize(rpc, chan, function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'ENOENT') {
|
|
||||||
|
|
||||||
// these channels no longer exists on the server
|
|
||||||
console.log(e, chan);
|
|
||||||
} else {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
} else if (msg && msg[0] && typeof(msg[0]) === 'number') {
|
|
||||||
bytes += msg[0];
|
|
||||||
//console.log(bytes);
|
|
||||||
} else {
|
|
||||||
console.log("returned message was not a number: ", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
--left;
|
|
||||||
if (left === 0) {
|
|
||||||
cb(void 0, bytes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var pinChannel = function (rpc, channel, cb) {
|
var pinChannel = function (rpc, channel, cb) {
|
||||||
@ -67,7 +41,8 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var reset = function (rpc, cb) {
|
var reset = function (rpc, cb) {
|
||||||
rpc.send('RESET', undefined, cb);
|
var list = uniqueChannelList();
|
||||||
|
rpc.send('RESET', list, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -80,7 +55,6 @@ define([
|
|||||||
UNPIN all, send all
|
UNPIN all, send all
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Don't use create until Cryptpad is ready
|
// Don't use create until Cryptpad is ready
|
||||||
// (use Cryptpad.ready)
|
// (use Cryptpad.ready)
|
||||||
var create = function (cb) {
|
var create = function (cb) {
|
||||||
@ -108,8 +82,8 @@ define([
|
|||||||
exp.getFileSize = function (file, cb) {
|
exp.getFileSize = function (file, cb) {
|
||||||
getFileSize(rpc, file, cb);
|
getFileSize(rpc, file, cb);
|
||||||
};
|
};
|
||||||
exp.getFileListSize = function (list, cb) {
|
exp.getFileListSize = function (cb) {
|
||||||
getFileListSize(rpc, list, cb);
|
getFileListSize(rpc, cb);
|
||||||
};
|
};
|
||||||
exp.getServerHash = function (cb) {
|
exp.getServerHash = function (cb) {
|
||||||
getServerHash(rpc, edPublic, cb);
|
getServerHash(rpc, edPublic, cb);
|
||||||
|
|||||||
@ -36,11 +36,6 @@ define([
|
|||||||
console.log(msg);
|
console.log(msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
call.getFileListSize(list, function (e, bytes) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
console.log("%s total bytes used", bytes);
|
|
||||||
});
|
|
||||||
|
|
||||||
call.getServerHash(function (e, hash) {
|
call.getServerHash(function (e, hash) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
console.log("the server believes your user hash is [%s]", hash);
|
console.log("the server believes your user hash is [%s]", hash);
|
||||||
@ -51,6 +46,11 @@ define([
|
|||||||
var localHash = call.localChannelsHash();
|
var localHash = call.localChannelsHash();
|
||||||
var serverHash;
|
var serverHash;
|
||||||
|
|
||||||
|
call.getFileListSize(function (e, bytes) {
|
||||||
|
if (e) { return void console.error(e); }
|
||||||
|
console.log("%s total bytes used", bytes);
|
||||||
|
});
|
||||||
|
|
||||||
call.getServerHash(function (e, hash) {
|
call.getServerHash(function (e, hash) {
|
||||||
if (e) { return void console.error(e); }
|
if (e) { return void console.error(e); }
|
||||||
serverHash = hash;
|
serverHash = hash;
|
||||||
@ -61,15 +61,9 @@ define([
|
|||||||
|
|
||||||
call.reset(function (e, response) {
|
call.reset(function (e, response) {
|
||||||
if (e) { return console.error(e); }
|
if (e) { return console.error(e); }
|
||||||
|
else {
|
||||||
var list = call.uniqueChannelList();
|
return console.log('reset pin list. new hash is [%s]', response);
|
||||||
|
}
|
||||||
// now start pinning...
|
|
||||||
list.forEach(function (channel) {
|
|
||||||
call.pin(channel, function (e, out) {
|
|
||||||
if (e) { return console.error(e); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html class="cp slide">
|
|
||||||
<head>
|
|
||||||
<title>CryptPad</title>
|
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
|
||||||
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="iframe-container">
|
|
||||||
<iframe id="pad-iframe"></iframe><script src="/common/noscriptfix.js"></script>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>PEWPEW
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
|
|
||||||
define([
|
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/rpc.js',
|
|
||||||
'/bower_components/jquery/dist/jquery.min.js',
|
|
||||||
], function (Cryptpad, RPC) {
|
|
||||||
var $ = window.jQuery;
|
|
||||||
var APP = window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
Cryptpad.ready(function (err, env) {
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
var proxy = Cryptpad.getStore().getProxy().proxy;
|
|
||||||
|
|
||||||
var edPrivate = proxy.edPrivate;
|
|
||||||
var edPublic = proxy.edPublic;
|
|
||||||
|
|
||||||
var payload = {
|
|
||||||
a: Math.floor(Math.random() * 1000),
|
|
||||||
b: 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
RPC.create(network, edPrivate, edPublic, function (e, rpc) {
|
|
||||||
// console.log(payload);
|
|
||||||
rpc.send('ECHO', payload, function (e, msg) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
// test a non-existent RPC call
|
|
||||||
rpc.send('PEWPEW', ['pew'], function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'UNSUPPORTED_RPC_CALL') { return; }
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
var list = Cryptpad.getUserChannelList();
|
|
||||||
if (list.length) {
|
|
||||||
rpc.send('GET_FILE_SIZE', list[0], function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc.send('GET_FILE_SIZE', 'pewpew', function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'INVALID_CHAN') { return; }
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
rpc.send('GET_FILE_SIZE', '26f014b2ab959418605ea37a6785f317', function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'ENOENT') { return; }
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.error("EXPECTED ENOENT");
|
|
||||||
console.log(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
// compute what you think the hash should be
|
|
||||||
|
|
||||||
// then ask the server if what it has matches your records
|
|
||||||
rpc.send('GET_HASH', edPublic, function (e, hash) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
|
|
||||||
|
|
||||||
console.log("user pins hash is [%s]", hash);
|
|
||||||
// if it does, awesome!
|
|
||||||
// you should be able to pin and unpin things easily
|
|
||||||
|
|
||||||
// if it doesn't, send a reset, and start re-pinning
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
}());
|
|
||||||
|
|
||||||
if (false) {
|
|
||||||
(function () {
|
|
||||||
var bytes = 0;
|
|
||||||
list.forEach(function (chan) {
|
|
||||||
rpc.send('GET_FILE_SIZE', chan, function (e, msg) {
|
|
||||||
if (e) {
|
|
||||||
if (e === 'ENOENT') {
|
|
||||||
return void console.log(e, chan);
|
|
||||||
}
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
if (msg && msg[0] && typeof(msg[0]) === 'number') {
|
|
||||||
bytes += msg[0];
|
|
||||||
console.log(bytes);
|
|
||||||
} else {
|
|
||||||
console.log(msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -13,10 +13,11 @@ define([
|
|||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/visible.js',
|
'/common/visible.js',
|
||||||
'/common/notify.js',
|
'/common/notify.js',
|
||||||
|
'/customize/application_config.js',
|
||||||
'/bower_components/secure-fabric.js/dist/fabric.min.js',
|
'/bower_components/secure-fabric.js/dist/fabric.min.js',
|
||||||
'/bower_components/jquery/dist/jquery.min.js',
|
'/bower_components/jquery/dist/jquery.min.js',
|
||||||
'/bower_components/file-saver/FileSaver.min.js',
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
], function (Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Visible, Notify) {
|
], function (Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Visible, Notify, AppConfig) {
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
|
|
||||||
@ -102,16 +103,12 @@ define([
|
|||||||
$width.on('change', updateBrushWidth);
|
$width.on('change', updateBrushWidth);
|
||||||
|
|
||||||
var pickColor = function (current, cb) {
|
var pickColor = function (current, cb) {
|
||||||
// TODO find out why initial color is not being set
|
|
||||||
// http://jsfiddle.net/j3hZB/
|
|
||||||
console.log(current);
|
|
||||||
var $picker = $('<input>', {
|
var $picker = $('<input>', {
|
||||||
type: 'color',
|
type: 'color',
|
||||||
value: '#FFFFFF',
|
value: '#FFFFFF',
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
visibility: 'hidden'
|
visibility: 'hidden'
|
||||||
//display: 'none',
|
|
||||||
})
|
})
|
||||||
.on('change', function () {
|
.on('change', function () {
|
||||||
var color = this.value;
|
var color = this.value;
|
||||||
@ -140,9 +137,10 @@ define([
|
|||||||
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO add a better color palette
|
var palette = AppConfig.whiteboardPalette || [
|
||||||
var palette = ['red', 'blue', 'green', 'white', 'black', 'purple',
|
'red', 'blue', 'green', 'white', 'black', 'purple',
|
||||||
'gray', 'beige', 'brown', 'cyan', 'darkcyan', 'gold', 'yellow', 'pink'];
|
'gray', 'beige', 'brown', 'cyan', 'darkcyan', 'gold', 'yellow', 'pink'
|
||||||
|
];
|
||||||
|
|
||||||
$('.palette-color').on('click', function () {
|
$('.palette-color').on('click', function () {
|
||||||
var color = $(this).css('background-color');
|
var color = $(this).css('background-color');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user