This commit is contained in:
Eason010212
2024-08-25 23:08:18 +08:00
parent a990f3b448
commit ca6be61078
24 changed files with 309 additions and 96 deletions

View File

@@ -18,7 +18,7 @@
<script src="js/codemirror.min.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/tf.min.js"></script>
<script src="js/blazeFace.js"></script>
<script src="js/faceapi.min.js"></script>
<script src="js/lang.js?v=5"></script>
<script src="js/lang2.js?v=5"></script>
<script src="js/farbtastic.js"></script>

File diff suppressed because one or more lines are too long

1
js/faceapi.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
[{"weights":[{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008194216092427571,"min":-0.9423348506291708}},{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006839508168837603,"min":-0.8412595047670252}},{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009194007106855804,"min":-1.2779669878529567}},{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036026100317637128,"min":-0.3170296827952067}},{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000740380117706224,"min":-0.06367269012273527}},{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0037702228508743585,"min":-0.6220867703942692}},{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0033707996209462483,"min":-0.421349952618281}},{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014611541991140328,"min":-1.8556658328748217}},{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002832523046755323,"min":-0.30307996600281956}},{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006593170586754294,"min":-0.6329443763284123}},{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.012215249211180444,"min":-1.6001976466646382}},{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002384825547536214,"min":-0.3028728445370992}},{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005859645441466687,"min":-0.7617539073906693}},{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013121426806730382,"min":-1.7845140457153321}},{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032247188044529336,"min":-0.46435950784122243}},{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002659512618008782,"min":-0.32977956463308894}},{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015499923743453681,"min":-1.9839902391620712}},{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032450980999890497,"min":-0.522460794098237}},{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005911862382701799,"min":-0.792189559282041}},{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021025861478319356,"min":-2.2077154552235325}},{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00349616945958605,"min":-0.46149436866535865}},{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008104994250278847,"min":-1.013124281284856}},{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029337059282789044,"min":-3.5791212325002633}},{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0038808938334969913,"min":-0.4230174278511721}},{"name":"fc/weights","shape":[128,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014016061670639936,"min":-1.8921683255363912}},{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029505149698724935,"min":0.088760145008564}}],"paths":["face_landmark_68_tiny_model-shard1"]}]

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
[{"paths":["mtcnn_model-shard1"],"weights":[{"dtype":"float32","name":"pnet/conv1/weights","shape":[3,3,3,10]},{"dtype":"float32","name":"pnet/conv1/bias","shape":[10]},{"dtype":"float32","name":"pnet/prelu1_alpha","shape":[10]},{"dtype":"float32","name":"pnet/conv2/weights","shape":[3,3,10,16]},{"dtype":"float32","name":"pnet/conv2/bias","shape":[16]},{"dtype":"float32","name":"pnet/prelu2_alpha","shape":[16]},{"dtype":"float32","name":"pnet/conv3/weights","shape":[3,3,16,32]},{"dtype":"float32","name":"pnet/conv3/bias","shape":[32]},{"dtype":"float32","name":"pnet/prelu3_alpha","shape":[32]},{"dtype":"float32","name":"pnet/conv4_1/weights","shape":[1,1,32,2]},{"dtype":"float32","name":"pnet/conv4_1/bias","shape":[2]},{"dtype":"float32","name":"pnet/conv4_2/weights","shape":[1,1,32,4]},{"dtype":"float32","name":"pnet/conv4_2/bias","shape":[4]},{"dtype":"float32","name":"rnet/conv1/weights","shape":[3,3,3,28]},{"dtype":"float32","name":"rnet/conv1/bias","shape":[28]},{"dtype":"float32","name":"rnet/prelu1_alpha","shape":[28]},{"dtype":"float32","name":"rnet/conv2/weights","shape":[3,3,28,48]},{"dtype":"float32","name":"rnet/conv2/bias","shape":[48]},{"dtype":"float32","name":"rnet/prelu2_alpha","shape":[48]},{"dtype":"float32","name":"rnet/conv3/weights","shape":[2,2,48,64]},{"dtype":"float32","name":"rnet/conv3/bias","shape":[64]},{"dtype":"float32","name":"rnet/prelu3_alpha","shape":[64]},{"dtype":"float32","name":"rnet/fc1/weights","shape":[576,128]},{"dtype":"float32","name":"rnet/fc1/bias","shape":[128]},{"dtype":"float32","name":"rnet/prelu4_alpha","shape":[128]},{"dtype":"float32","name":"rnet/fc2_1/weights","shape":[128,2]},{"dtype":"float32","name":"rnet/fc2_1/bias","shape":[2]},{"dtype":"float32","name":"rnet/fc2_2/weights","shape":[128,4]},{"dtype":"float32","name":"rnet/fc2_2/bias","shape":[4]},{"dtype":"float32","name":"onet/conv1/weights","shape":[3,3,3,32]},{"dtype":"float32","name":"onet/conv1/bias","shape":[32]},{"dtype":"float32","name":"onet/prelu1_alpha","shape":[32]},{"dtype":"float32","name":"onet/conv2/weights","shape":[3,3,32,64]},{"dtype":"float32","name":"onet/conv2/bias","shape":[64]},{"dtype":"float32","name":"onet/prelu2_alpha","shape":[64]},{"dtype":"float32","name":"onet/conv3/weights","shape":[3,3,64,64]},{"dtype":"float32","name":"onet/conv3/bias","shape":[64]},{"dtype":"float32","name":"onet/prelu3_alpha","shape":[64]},{"dtype":"float32","name":"onet/conv4/weights","shape":[2,2,64,128]},{"dtype":"float32","name":"onet/conv4/bias","shape":[128]},{"dtype":"float32","name":"onet/prelu4_alpha","shape":[128]},{"dtype":"float32","name":"onet/fc1/weights","shape":[1152,256]},{"dtype":"float32","name":"onet/fc1/bias","shape":[256]},{"dtype":"float32","name":"onet/prelu5_alpha","shape":[256]},{"dtype":"float32","name":"onet/fc2_1/weights","shape":[256,2]},{"dtype":"float32","name":"onet/fc2_1/bias","shape":[2]},{"dtype":"float32","name":"onet/fc2_2/weights","shape":[256,4]},{"dtype":"float32","name":"onet/fc2_2/bias","shape":[4]},{"dtype":"float32","name":"onet/fc2_3/weights","shape":[256,10]},{"dtype":"float32","name":"onet/fc2_3/bias","shape":[10]}]}]

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
[{"weights":[{"name":"conv0/filters","shape":[3,3,3,16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009007044399485869,"min":-1.2069439495311063}},{"name":"conv0/bias","shape":[16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005263455241334205,"min":-0.9211046672334858}},{"name":"conv1/depthwise_filter","shape":[3,3,16,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004001977630690033,"min":-0.5042491814669441}},{"name":"conv1/pointwise_filter","shape":[1,1,16,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013836609615999109,"min":-1.411334180831909}},{"name":"conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0015159862590771096,"min":-0.30926119685173037}},{"name":"conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002666276225856706,"min":-0.317286870876948}},{"name":"conv2/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015265831292844286,"min":-1.6792414422128714}},{"name":"conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0020280554598453,"min":-0.37113414915168985}},{"name":"conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006100742489683862,"min":-0.8907084034938438}},{"name":"conv3/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016276211832083907,"min":-2.0508026908425725}},{"name":"conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394414279975143,"min":-0.7637432129944072}},{"name":"conv4/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006716050119961009,"min":-0.8059260143953211}},{"name":"conv4/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021875603993733724,"min":-2.8875797271728514}},{"name":"conv4/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0041141652009066415,"min":-0.8187188749804216}},{"name":"conv5/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008423839597141042,"min":-0.9013508368940915}},{"name":"conv5/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.030007277283014035,"min":-3.8709387695088107}},{"name":"conv5/bias","shape":[512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008402082966823203,"min":-1.4871686851277068}},{"name":"conv8/filters","shape":[1,1,512,25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.028336129469030042,"min":-4.675461362389957}},{"name":"conv8/bias","shape":[25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002268134028303857,"min":-0.41053225912299807}}],"paths":["tiny_face_detector_model-shard1"]}]

View File

@@ -262,6 +262,7 @@ function run_project() {
if ((typeof Notification) != "undefined")
Notification.requestPermission();
isRunning = true
$(".facial").attr("hidden", "hidden")
try {
var logicFunction = Function(globalCode);
logicFunction()
@@ -287,6 +288,7 @@ function run_project() {
function stop_project() {
isRunning = false
$(".facial").removeAttr("hidden")
$("#grid").addClass("gridbg")
$("#grid").children(".item").removeClass("itemrun")
$("#grid").children(".item").draggable({
@@ -1348,7 +1350,6 @@ function view_project(projectName, projectType) {
cvtName = JSLang[lang].time
else if (cvtName == "值")
cvtName = JSLang[lang].value
console.log(cvtName)
tableFields.push({
name: cvtName,
type: 'text',

View File

@@ -134,7 +134,7 @@ function showtext(text){
});
d.showModal();
setTimeout(function(){
d.close()
d.close().remove();
},1000)
}

View File

@@ -5,7 +5,7 @@
*/
tbd = undefined;
lastFacePublishTime = false;
function add_block(width, height, contents, attrs) {
var itemdiv = $("<div/>")
itemdiv.attr("class", "item")
@@ -5937,13 +5937,74 @@ function add_face(user_title, user_topic, user_content, user_style, title_style)
cameraDiv.append(video)
// floating canvas on top of the video
var canvas = $("<canvas style='position:absolute;top:0;left:0'/>")
var canvas2 = $("<canvas style='position:absolute;top:0;left:0;display:none'/>")
cameraDiv.append(canvas)
cameraDiv.append(canvas2)
var addFacialDataButton = $('<a class="btn btn-primary facial" style="position:absolute;bottom:10px;right:10px;box-shadow:1px 1px 5px #4e73df"><i class="fa fa-plus"></i> 新增当前人脸数据</a>')
contents.push(addFacialDataButton)
// stopPropagation
addFacialDataButton.bind('mousedown', function(event) {
event.stopPropagation()
})
addFacialDataButton.bind('mouseup', function(event) {
event.stopPropagation()
})
if (window.screen.width > 800)
addFacialDataButton.bind('click', function(event) {
event.stopPropagation()
})
else
addFacialDataButton.bind('touchend', function(event) {
event.stopPropagation()
})
var landmarks = false
var isMouthOpen = -1
addFacialDataButton.click(function() {
if(landmarks)
{
// 备份当前landmarks
var data = []
for (var i = 0; i < landmarks.length; i++)
{
data.push(landmarks[i])
}
// 获取当前的user-content
var user_content = title.parent().parent().attr('user-content')
if (user_content == undefined || user_content == "")
user_content = "[]"
// 读取当前的user-content
var user_data = JSON.parse(user_content)
user_data.push(data)
title.parent().parent().attr('user-content', JSON.stringify(user_data))
showtext("人脸数据已保存。ID:" + (user_data.length - 1))
}
else
{
showtext("未检测到人脸")
}
})
var removeAllFacialDataButton = $('<a class="btn btn-danger facial" style="position:absolute;bottom:10px;left:10px;box-shadow:1px 1px 5px #e74a3b"><i class="fa fa-trash"></i> 删除所有人脸数据</a>')
contents.push(removeAllFacialDataButton)
removeAllFacialDataButton.bind('mousedown', function(event) {
event.stopPropagation()
})
removeAllFacialDataButton.bind('mouseup', function(event) {
event.stopPropagation()
}
)
if (window.screen.width > 800)
removeAllFacialDataButton.bind('click', function(event) {
event.stopPropagation()
})
else
removeAllFacialDataButton.bind('touchend', function(event) {
event.stopPropagation()
}
)
removeAllFacialDataButton.click(function() {
title.parent().parent().attr('user-content', "[]")
showtext("所有人脸数据已删除")
})
var ctx = canvas[0].getContext('2d')
// 居中显示Loading...
var ctx2 = canvas2[0].getContext('2d')
navigator.mediaDevices.getUserMedia({
video: {
width: {
@@ -5963,76 +6024,92 @@ function add_face(user_title, user_topic, user_content, user_style, title_style)
ctx.font = "30px Arial"
ctx.fillStyle = "#4e73df"
ctx.textAlign = "center"
ctx.fillText("Loading...", canvas.width() / 2, canvas.height() / 2)
blazeface.load().then(function(model) {
// 关闭镜面翻转
const returnTensors = false;
const flipHorizontal = false;
const annotateBoxes = true;
var fresh = function(){
// if video ready
if (video[0].readyState >1 && isAlive) {
// video element size, not the video resolution
canvas[0].height = cameraDiv.height()
canvas[0].width = cameraDiv.width()
canvas2[0].height = cameraDiv.height()
canvas2[0].width = cameraDiv.width()
// 在canvas中居中绘制缩放到合适大小
var scale = Math.min(canvas.width() / video[0].videoWidth, canvas.height() / video[0].videoHeight)
var x = (canvas.width() - video[0].videoWidth * scale) / 2
var y = (canvas.height() - video[0].videoHeight * scale) / 2
ctx2.clearRect(0, 0, canvas2.width(), canvas2.height())
ctx2.drawImage(video[0], x, y, video[0].videoWidth * scale, video[0].videoHeight * scale)
model.estimateFaces(canvas2[0], returnTensors, flipHorizontal, annotateBoxes).then(predictions => {
if (predictions.length > 0) {
for (let i = 0; i < predictions.length; i++) {
if (returnTensors) {
predictions[i].topLeft = predictions[i].topLeft.arraySync();
predictions[i].bottomRight = predictions[i].bottomRight.arraySync();
if (annotateBoxes) {
predictions[i].landmarks = predictions[i].landmarks.arraySync();
}
}
const start = predictions[i].topLeft;
const end = predictions[i].bottomRight;
const size = [end[0] - start[0], end[1] - start[1]];
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 四角框,标记人脸位置
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
ctx.fillRect(start[0], start[1], size[0], size[1]);
if (annotateBoxes) {
const landmarks = predictions[i].landmarks
if(isAlive && isRunning){
var landmark_dict = {}
var landmark_names = ['left_eye', 'right_eye', 'nose', 'mouth', 'left_ear', 'right_ear']
for (let j = 0; j < landmarks.length; j++) {
const x = landmarks[j][0];
const y = landmarks[j][1];
const name = landmark_names[j];
landmark_dict[name+'_x'] = x
landmark_dict[name+'_y'] = y
}
publish(user_topic, JSON.stringify(landmark_dict))
}
ctx.fillStyle = 'blue';
for (let j = 0; j < landmarks.length; j++) {
const x = landmarks[j][0];
const y = landmarks[j][1];
ctx.fillRect(x, y, 5, 5);
}
}
}
}
}).catch(err => {
console.log(err)
})
}
}
// wait for the video to be loaded
setInterval(fresh, 500)
})
ctx.fillText("Loading...", 100, 100)
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('./js/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('./js/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('./js/models'),
faceapi.nets.faceExpressionNet.loadFromUri('./js/models'),
]).then(function(){
var displaySize = { width: cameraDiv.width(), height: cameraDiv.height() }
faceapi.matchDimensions(canvas[0], displaySize)
setInterval(async () => {
// 识别位置, 脸部特征, 表情
// 设置最低置信度 0.4,最多检测一张脸
var options = new faceapi.TinyFaceDetectorOptions({ inputSize: 256, scoreThreshold: 0.4 })
const detections = await faceapi
.detectAllFaces(video[0], options)
.withFaceLandmarks()
.withFaceExpressions()
.withFaceDescriptors()
// 调整尺寸
const resizedDetections = faceapi.resizeResults(detections, displaySize);
// 如果有人脸, 则保存用以进行人脸匹配的特征向量
if(resizedDetections.length > 0)
{
// 获取RecogntionNet的128维特征向量
landmarks = resizedDetections[0].descriptor
// 计算嘴是否张开
if(resizedDetections[0].expressions.happy > 0.5 || resizedDetections[0].expressions.surprised > 0.5)
isMouthOpen = 1
else
isMouthOpen = 0
}
else
{
landmarks = false
isMouthOpen = -1
}
// 尝试匹配user-content中的人脸数据
var user_content = title.parent().parent().attr('user-content')
if (user_content == undefined || user_content == "")
user_content = "[]"
var user_data = JSON.parse(user_content)
var min_euclidean_distance = 0.4
var min_index = -1
for (var i = 0; i < user_data.length; i++)
{
var euclidean_distance = 0
for (var j = 0; j < user_data[i].length; j++)
{
euclidean_distance += Math.pow(user_data[i][j] - landmarks[j], 2)
}
euclidean_distance = Math.sqrt(euclidean_distance)
if(euclidean_distance < min_euclidean_distance)
{
min_euclidean_distance = euclidean_distance
min_index = i
}
}
canvas[0].getContext('2d')?.clearRect(0, 0, canvas[0].width, canvas[0].height); // 清空画布
//faceapi.draw.drawDetections(canvas[0], resizedDetections); // 位置
faceapi.draw.drawFaceLandmarks(canvas[0], resizedDetections); // 脸部特征
faceapi.draw.drawFaceExpressions(canvas[0], resizedDetections); // 表情
if(resizedDetections.length > 0)
{
ctx.font = "30px Arial"
ctx.fillStyle = "#ff0000"
if(min_index == -1)
{
const drawBox = new faceapi.draw.DrawBox(resizedDetections[0].detection.box, {"label":"ID:Unknown Mouth: " + (isMouthOpen == 1 ? "Open" : "Close")})
drawBox.draw(canvas[0])
}
else
{
const drawBox = new faceapi.draw.DrawBox(resizedDetections[0].detection.box, {"label":"ID:" + min_index + " Mouth: " + (isMouthOpen == 1 ? "Open" : "Close")})
drawBox.draw(canvas[0])
}
if(!lastPublishTime || new Date().getTime() - lastFacePublishTime >= 500)
{
publish(user_topic, JSON.stringify({id: min_index, isMouthOpen: isMouthOpen, face_probability: resizedDetections[0].detection.score, happy_probability: resizedDetections[0].expressions.happy, sad_probability: resizedDetections[0].expressions.sad, angry_probability: resizedDetections[0].expressions.angry, surprised_probability: resizedDetections[0].expressions.surprised, disgusted_probability: resizedDetections[0].expressions.disgusted, fearful_probability: resizedDetections[0].expressions.fearful}))
lastFacePublishTime = new Date().getTime()
}
}
}, 100);
})
})
@@ -6079,8 +6156,8 @@ function add_face(user_title, user_topic, user_content, user_style, title_style)
if (countSubstr(grid.html(), 'user-title=\"' + title_input.val() + '\"', false) <= (title_input.val() == title.text() ? 1 : 0)) {
title.parent().parent().attr('user-title', title_input.val())
title.parent().parent().attr('user-topic', topic_input.val())
if (title.parent().parent().attr('user-content') == undefined)
title.parent().parent().attr('user-content', "")
if (title.parent().parent().attr('user-content') == undefined || title.parent().parent().attr('user-content') == "")
title.parent().parent().attr('user-content', "[]")
title.text(title_input.val())
topic.text(topic_input.val())
modifyDia.close()