Compare commits
337 Commits
CinekidRel
...
master
Author | SHA1 | Date |
---|---|---|
peteruithoven | f8032d7411 | |
peteruithoven | 2acb06c3ed | |
peteruithoven | daed62937c | |
peteruithoven | 058fff8b34 | |
peteruithoven | 28808078ad | |
peteruithoven | 4e18fa0f56 | |
peteruithoven | 225a173da7 | |
peteruithoven | d2bc62b092 | |
peteruithoven | 28ce8ff479 | |
peteruithoven | fbcdaad54a | |
Wouter R | 4a3da30ebd | |
Wouter R | 533968bb04 | |
Wouter R | 0a9ceee49a | |
Wouter R | 50d964e611 | |
Wouter R | 656e37670e | |
Wouter R | 4752199cfb | |
Wouter R | c742740078 | |
Wouter R | 578fba4f63 | |
Wouter R | bca548def5 | |
Wouter R | a5d3e88f0a | |
Wouter R | 456531b15f | |
Wouter R | 4f5e1143b4 | |
Wouter R | a9f7fe1c78 | |
Wouter R | 8f0943a53b | |
Wouter R | 5c07947fe5 | |
Wouter R | d48944e448 | |
Wouter R | 46bcd54a1a | |
peteruithoven | 25c51c3e5c | |
Wouter R | c2f5f890c7 | |
peteruithoven | 09fcdbea31 | |
peteruithoven | 969178b096 | |
peteruithoven | 58ad430e13 | |
Arne Boon | a7d253203a | |
Arne Boon | 38b43e5263 | |
peteruithoven | 9a24230112 | |
peteruithoven | a823c4cc25 | |
peteruithoven | 6835a7056c | |
Rick Companje | 8d2d4a9f57 | |
Rick Companje | 2fba2b34a1 | |
Rick Companje | 95f5ce97b5 | |
Rick Companje | 31b16b2a3f | |
Rick Companje | 18d1aacc71 | |
Rick Companje | 58b930cefa | |
Rick Companje | c6b6a3c448 | |
Rick Companje | 3d99c146a0 | |
Wouter R | 27e794876b | |
peteruithoven | 6202f9febd | |
peteruithoven | 53843f499c | |
peteruithoven | 953d50e5fc | |
peteruithoven | 72d2e859f7 | |
peteruithoven | 248de728c6 | |
Rick Companje | 4d986a3528 | |
Rick Companje | c4593a4dc3 | |
Rick Companje | 7441b848f3 | |
Rick Companje | d2ab7fc08b | |
Wouter R | 494aca34bc | |
peteruithoven | f3577669d2 | |
peteruithoven | 0acf442a46 | |
peteruithoven | 64d1c32f09 | |
Wouter R | fee0a4f480 | |
Wouter R | ee6bab1c5a | |
peteruithoven | 71cbc779f2 | |
Wouter R | 2eaf21a030 | |
Wouter R | e050c8e080 | |
Wouter R | 2457ce656e | |
peteruithoven | 5c5d45088a | |
Wouter R | 9a620fd9ce | |
Wouter R | 0b52f928ca | |
Wouter R | afb279fbc7 | |
Wouter R | ce489112e8 | |
peteruithoven | b3d3501270 | |
peteruithoven | daba2ef1c6 | |
peteruithoven | 26c864a301 | |
peteruithoven | 90d1a80355 | |
peteruithoven | 80a4d18cd5 | |
peteruithoven | 017020194f | |
peteruithoven | d432c00336 | |
peteruithoven | d8dea626fe | |
peteruithoven | 079ed5a164 | |
peteruithoven | 05e49a54ff | |
peteruithoven | 1394a28c18 | |
peteruithoven | 03491999c6 | |
peteruithoven | cc814bc827 | |
peteruithoven | 16078d3478 | |
peteruithoven | eaed4c9efc | |
peteruithoven | c058f40b8b | |
peteruithoven | 1dbbf0c88c | |
peteruithoven | fd8520698e | |
peteruithoven | 652192d42d | |
peteruithoven | 932ad198ec | |
peteruithoven | c4ec82c9a7 | |
peteruithoven | 556fc0dd1e | |
peteruithoven | 4ef164fb17 | |
peteruithoven | 6cac5fc6f5 | |
peteruithoven | 1523ba3227 | |
peteruithoven | 42e43c9a38 | |
peteruithoven | 219bd190c0 | |
peteruithoven | 59c26a6713 | |
peteruithoven | f0106e6db0 | |
peteruithoven | 36d336663e | |
Wouter R | 2427856be9 | |
peteruithoven | 98d836b321 | |
peteruithoven | 0b33b87009 | |
peteruithoven | 6d71db1e84 | |
peteruithoven | 735cff2edd | |
peteruithoven | fcf966b2e3 | |
peteruithoven | 8ec5772f77 | |
peteruithoven | 320c5c7d18 | |
peteruithoven | 9bad257922 | |
peteruithoven | 8a4ab7c519 | |
peteruithoven | f2a3772b75 | |
peteruithoven | eef5307464 | |
peteruithoven | 58eec424df | |
Wouter R | e1206f73d4 | |
Wouter R | 304657a104 | |
peteruithoven | 996a6d5300 | |
peteruithoven | 4185865289 | |
peteruithoven | 7f5079d2cb | |
Wouter R | 92a28f54b8 | |
Wouter R | de757cae0a | |
Wouter R | 7288ac8b1e | |
peteruithoven | 679cf9b5a5 | |
peteruithoven | 6dafeafa37 | |
peteruithoven | 577bc28bc9 | |
peteruithoven | cb857ae6fe | |
Wouter R | 74b9149175 | |
Wouter R | 5eb129d2a2 | |
Wouter R | d634f2e9c3 | |
Wouter R | 032d6413f7 | |
peteruithoven | 62f2bc824b | |
peteruithoven | 8b229c0aff | |
Wouter R | b25044d2d6 | |
peteruithoven | bc4426faba | |
peteruithoven | 88b711d1f3 | |
Wouter R | 1098c86dd5 | |
Wouter R | 06ff438119 | |
Wouter R | fd6c55b69e | |
peteruithoven | 725fb6d015 | |
peteruithoven | efe1f72b02 | |
peteruithoven | e56d4bcd84 | |
Wouter R | 57c928f195 | |
peteruithoven | c6058ed61d | |
peteruithoven | 0c8856587d | |
peteruithoven | 31cec107b0 | |
peteruithoven | bbed35d877 | |
peteruithoven | 548ea2732a | |
peteruithoven | f371481c27 | |
peteruithoven | f67d9a476e | |
peteruithoven | e9a2b90483 | |
peteruithoven | 0b908a8f44 | |
peteruithoven | 17467edae1 | |
peteruithoven | 63a280ab18 | |
peteruithoven | ed3a769639 | |
peteruithoven | 942d9d8bbf | |
peteruithoven | a01599fb54 | |
peteruithoven | 7d726f513e | |
peteruithoven | 89ee355b2e | |
peteruithoven | fc8c83ae19 | |
peteruithoven | a952a1ee7b | |
Wouter R | c697806385 | |
Wouter R | e8c9932014 | |
Wouter R | 97201587c0 | |
Wouter R | e125939db8 | |
peteruithoven | 606f7cb359 | |
peteruithoven | d68b9cbefc | |
peteruithoven | 01f28a2403 | |
peteruithoven | ab329aaaf1 | |
Wouter R | 295ba222a3 | |
Wouter R | 44f6534f9e | |
peteruithoven | d156dc9902 | |
peteruithoven | b2fd2a2f77 | |
peteruithoven | 82b57def39 | |
peteruithoven | f7fec0aec6 | |
peteruithoven | 139e4ca6ae | |
peteruithoven | a4ad7d7198 | |
Wouter R | af95065bbe | |
Rick Companje | 0ad800b021 | |
Rick Companje | 2cdeaacd14 | |
Wouter R | 292f798f9a | |
Wouter R | 97377a7b19 | |
peteruithoven | ae5950eb08 | |
peteruithoven | d5220225cc | |
peteruithoven | d18b420365 | |
peteruithoven | dfcd3ee2c2 | |
peteruithoven | 14789ea046 | |
peteruithoven | 136799e16c | |
peteruithoven | 1f1b6c89dd | |
peteruithoven | d50a42ef09 | |
Wouter R | 2d8c385e02 | |
Wouter R | 744862b6a1 | |
peteruithoven | f0492e9246 | |
peteruithoven | 8222591041 | |
peteruithoven | fc48b4de85 | |
peteruithoven | f2f4727482 | |
peteruithoven | f077fdd484 | |
peteruithoven | 8b0b8884ed | |
Wouter R | d0806a0ea1 | |
peteruithoven | 457cb756ad | |
Wouter R | aa585236b8 | |
Wouter R | 076b69500e | |
Rick Companje | 997c34a532 | |
peteruithoven | 238a9812e2 | |
Rick Companje | 9f0ab35cbd | |
Rick Companje | 2edba7a4c9 | |
peteruithoven | c3fa844966 | |
Rick Companje | 4799a7e95e | |
Rick Companje | ff6df2f041 | |
Rick Companje | b85d3244c9 | |
peteruithoven | dd6c1d8034 | |
peteruithoven | 9b802ceea9 | |
peteruithoven | ff397700b7 | |
peteruithoven | 965119de33 | |
Wouter R | eb2736afcb | |
Wouter R | a545f8f2b1 | |
Wouter R | c2d6c2274e | |
peteruithoven | d92a2bcb3c | |
peteruithoven | d89e440cd9 | |
peteruithoven | 3ff0eb921e | |
peteruithoven | f98dc488d4 | |
Wouter R | ea2d50fd60 | |
Wouter R | fe9c2cc5ea | |
peteruithoven | d715d19412 | |
peteruithoven | c8f0ad4409 | |
Rick Companje | 8b76a17ef7 | |
Adriaan Wormgoor | 41f8232ebb | |
Adriaan Wormgoor | f9f64f7133 | |
Rick Companje | 1da8ff05d0 | |
Rick Companje | 0b5cf1a5f4 | |
Adriaan Wormgoor | e7ef6eccc4 | |
Adriaan Wormgoor | 176f8f4ae1 | |
Adriaan Wormgoor | 09f60b8f4b | |
peteruithoven | 8745e037a4 | |
Adriaan Wormgoor | 7003aefe66 | |
peteruithoven | 5f15b9945c | |
peteruithoven | 159adb8df8 | |
peteruithoven | b57dab9826 | |
Adriaan Wormgoor | e6e34e4ca6 | |
Adriaan Wormgoor | 69b50cc55d | |
Adriaan Wormgoor | d53f1c3e0f | |
Adriaan Wormgoor | 68bcd4834a | |
Adriaan Wormgoor | ef7a147a5b | |
peteruithoven | 3e6dde503e | |
peteruithoven | 9ead4a9416 | |
peteruithoven | cfff8b498f | |
peteruithoven | f783726c47 | |
peteruithoven | 96a48b38d9 | |
peteruithoven | 636d00370a | |
peteruithoven | b67c24d750 | |
peteruithoven | 2e09d8bccb | |
peteruithoven | 8550cc586a | |
Adriaan Wormgoor | 341fb637b8 | |
Adriaan Wormgoor | 05f2c58aa9 | |
Adriaan Wormgoor | 8482d1f278 | |
Adriaan Wormgoor | 7057a92da6 | |
Adriaan Wormgoor | 52d7da85fe | |
Wouter R | 5ebaf0e654 | |
Wouter R | 1155cad8c2 | |
peteruithoven | c1160c60a7 | |
Adriaan Wormgoor | f3e45662ad | |
Adriaan Wormgoor | 8350425070 | |
Wouter R | 2e93202bfc | |
Wouter R | 98e0418eb8 | |
peteruithoven | 4cf3ef2d58 | |
Adriaan Wormgoor | e579c27284 | |
Adriaan Wormgoor | d4eaadfcb9 | |
Adriaan Wormgoor | 099711b33e | |
peteruithoven | ceb89b9664 | |
peteruithoven | f59feb7d44 | |
peteruithoven | c3fb6fc016 | |
Adriaan Wormgoor | 7cc5b01b37 | |
Adriaan Wormgoor | 3058ef5c79 | |
peteruithoven | 8bd62c93ec | |
peteruithoven | 2b319c5dd6 | |
peteruithoven | 580b0ef33e | |
peteruithoven | 11c1764074 | |
peteruithoven | cc2bcf962c | |
Wouter R | 3b192078b4 | |
peteruithoven | f7bcd6e7c4 | |
Adriaan Wormgoor | 7daa661f3c | |
Adriaan Wormgoor | 06a969446a | |
Adriaan Wormgoor | d7d30f8167 | |
Adriaan Wormgoor | ff98a24526 | |
Adriaan Wormgoor | d3029096a7 | |
Wouter R | 9fc106b916 | |
Wouter R | 56d404522a | |
Wouter R | 77a58849e8 | |
Wouter R | 81bdabd2d5 | |
Wouter R | 02d026e52a | |
Wouter R | db4ed0df8a | |
Wouter R | 86dcb57677 | |
Wouter R | 21b5f5d03e | |
Wouter R | feae8ba3e6 | |
Wouter R | 6e79e70c0b | |
Wouter R | 1f79986f54 | |
Wouter R | 7b44b52cdd | |
Adriaan Wormgoor | df98330259 | |
Adriaan Wormgoor | cda7b43163 | |
Adriaan Wormgoor | 476e7d3e2d | |
Adriaan Wormgoor | b3823c1fc5 | |
peteruithoven | 4899f7f510 | |
peteruithoven | d06008b3dc | |
Adriaan Wormgoor | b55a9be25f | |
Adriaan Wormgoor | f0f97198ec | |
Adriaan Wormgoor | 90e00913ab | |
Adriaan Wormgoor | 447b245c5b | |
peteruithoven | 48a602e856 | |
Wouter R | 9c9086ab91 | |
Wouter R | 28c179aa77 | |
Adriaan Wormgoor | 13b500f267 | |
Adriaan Wormgoor | eb2f941639 | |
Adriaan Wormgoor | 8289c084ca | |
peteruithoven | bc15491bf4 | |
Adriaan Wormgoor | 4ec660fd74 | |
Adriaan Wormgoor | 66271c5287 | |
Adriaan Wormgoor | 524643e28a | |
peteruithoven | 2950638873 | |
peteruithoven | 10724b1746 | |
peteruithoven | 46d2ae4bfc | |
peteruithoven | 5ceabf41ba | |
peteruithoven | 10ca22d7e9 | |
peteruithoven | b978b5ada5 | |
peteruithoven | 53e8ccc294 | |
Adriaan Wormgoor | b2191217cb | |
Adriaan Wormgoor | b89f2385b8 | |
Adriaan Wormgoor | 69933b3b41 | |
Adriaan Wormgoor | 5c9c8c8e8c | |
Adriaan Wormgoor | e01175ed81 | |
Adriaan Wormgoor | 7d9b099aec | |
peteruithoven | ff14078d46 | |
peteruithoven | b1ded5d41b | |
peteruithoven | d5aef3bf95 | |
peteruithoven | 9ab36d999e | |
Adriaan Wormgoor | 1df94100f3 | |
Adriaan Wormgoor | b32f6d8c61 | |
peteruithoven | 828a6a3b0a | |
peteruithoven | 6419af4055 | |
peteruithoven | 50cb44b865 |
|
@ -1,2 +1,28 @@
|
|||
|
||||
.project
|
||||
|
||||
.idea/*
|
||||
www/js/*.js
|
||||
www/js/libs/*.js
|
||||
www/css/styles.css
|
||||
www/css/*.min.css
|
||||
__index.html
|
||||
_index.html
|
||||
div_bgs.html
|
||||
img/thermo_bg_2.png
|
||||
img/thermo_fg_2.png
|
||||
img/logo/logo_full_8bit.png
|
||||
img/logo/logo_small BACKUP.png
|
||||
img/logo/logo_small_8bit.png
|
||||
img/logo/logo_smaller.png
|
||||
img/logo/logo_smaller_8bit.png
|
||||
img/logo/logo_smaller_wide_8bit.png
|
||||
img/logo/logo_smallest.png
|
||||
d3d_btns.css
|
||||
js/main.js.orig
|
||||
less/verticalshapes.css
|
||||
less/verticalshapes_backup.css
|
||||
__settings.html
|
||||
css/_settings.css
|
||||
node_modules/*
|
||||
js/main.js.out
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="node_modules/|www/" kind="src" path="">
|
||||
<attributes>
|
||||
<attribute name="provider" value="org.eclipse.wst.jsdt.web.core.internal.project.ModuleSourcePathProvider"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
|
||||
<attributes>
|
||||
<attribute name="hide" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path=""/>
|
||||
</classpath>
|
|
@ -0,0 +1,2 @@
|
|||
eclipse.preferences.version=1
|
||||
included=//*.js
|
|
@ -0,0 +1,2 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
|
@ -0,0 +1 @@
|
|||
Window
|
|
@ -0,0 +1,182 @@
|
|||
/*global module:false*/
|
||||
module.exports = function(grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
// Metadata.
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
|
||||
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
|
||||
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
|
||||
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
|
||||
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
|
||||
gitinfo: {
|
||||
options: {},
|
||||
commands: { 'tag': ['tag', '--points-at', 'HEAD'] }
|
||||
},
|
||||
template: {
|
||||
'add_build_info': {
|
||||
options: {
|
||||
data: function() {
|
||||
grunt.task.requires('gitinfo');
|
||||
var gi = grunt.config('gitinfo');
|
||||
var lbc = gi.local.branch.current;
|
||||
|
||||
var tags = (gi.tag == '') ? 'no_tag' : gi.tag;
|
||||
tags = tags.split('\n').join(',');
|
||||
var commitMsg = lbc.lastCommitMessage.slice(1, -1).split('\n')[0].replace(/"/g, '\\\"');
|
||||
|
||||
var buildInfo = lbc.shortSHA + "/" + lbc.name + "/" + tags +
|
||||
" (" + lbc.lastCommitTime.slice(1, -1) + "; \'" + commitMsg + "'";
|
||||
return { 'build_info': buildInfo };
|
||||
}
|
||||
},
|
||||
files: {
|
||||
'js/main.js.out': ['js/main.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
options: {
|
||||
// separator: ';'
|
||||
},
|
||||
js: {
|
||||
src: [
|
||||
'js/api/*.js',
|
||||
'js/settings/FormPanel.js',
|
||||
'js/settings/*.js',
|
||||
'js/*.js',
|
||||
// make sure we put main.js last
|
||||
'!js/main.js',
|
||||
'js/main.js.out'
|
||||
],
|
||||
dest: 'www/js/<%= pkg.name %>.js'
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
// banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
|
||||
mangle: true,
|
||||
beautify: false,
|
||||
compress: {},
|
||||
// report: 'min',
|
||||
preserveComments: 'some'
|
||||
},
|
||||
js: {
|
||||
files: {
|
||||
'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js']
|
||||
}
|
||||
},
|
||||
jslibs: {
|
||||
cwd: "js/libs/",
|
||||
// src: ['js/libs/*.js', '!js/libs/*.min.js'], // source files mask
|
||||
src: ['*.js', '!*.min.js'], // source files mask
|
||||
dest: 'www/js/libs/', // destination folder
|
||||
expand: true, // allow dynamic building
|
||||
flatten: true, // remove all unnecessary nesting
|
||||
ext: '.min.js' // replace .js to .min.js
|
||||
// files: {
|
||||
// 'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js']
|
||||
// }
|
||||
}
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
globals: {
|
||||
jQuery: true
|
||||
},
|
||||
browser: true,
|
||||
curly: true,
|
||||
eqeqeq: true,
|
||||
immed: true,
|
||||
latedef: true,
|
||||
newcap: true,
|
||||
noarg: true,
|
||||
sub: true,
|
||||
undef: true,
|
||||
unused: true,
|
||||
boss: true,
|
||||
eqnull: true
|
||||
},
|
||||
// gruntfile: {
|
||||
// src: 'Gruntfile.js'
|
||||
// },
|
||||
lib_test: {
|
||||
src: ['www/js/*.js', '!www/js/<%= pkg.name %>.js', '!www/js/<%= pkg.name %>.min.js']
|
||||
}
|
||||
},
|
||||
less: {
|
||||
development: {
|
||||
options: {
|
||||
paths: ["www/css"]
|
||||
},
|
||||
files: {
|
||||
"www/css/styles.css": "less/styles.less"
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
javascript: {
|
||||
files: ["js/**", '!www/js/<%= pkg.name %>.min.js', '!www/js/<%= pkg.name %>.js'],
|
||||
tasks: ["concat:js", "uglify:js"]
|
||||
// tasks: ["jshint", "concat", "uglify"]
|
||||
},
|
||||
javascriptLibs: {
|
||||
files: ["js/libs/*"],
|
||||
tasks: ["uglify:jslibs"]
|
||||
// tasks: ["jshint", "concat", "uglify"]
|
||||
},
|
||||
styles: {
|
||||
files: ["less/*"],
|
||||
tasks: ["less", "autoprefixer", "cssmin"]
|
||||
}
|
||||
},
|
||||
autoprefixer: {
|
||||
options: {
|
||||
browsers: ['> 1%', 'last 2 versions', 'ie 8', 'ie 9', 'ff 17', 'opera 12.1']
|
||||
},
|
||||
// prefix all specified files and save them separately
|
||||
single_file: {
|
||||
options: {},
|
||||
// expand: true,
|
||||
// flatten: true,
|
||||
src: 'www/css/styles.css', // -> src/css/file1.css, src/css/file2.css
|
||||
dest: 'www/css/styles.css' // -> dest/css/file1.css, dest/css/file2.css
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
minify: {
|
||||
expand: true,
|
||||
cwd: 'www/css/',
|
||||
src: ['*.css', '!*.min.css'],
|
||||
dest: 'www/css/',
|
||||
ext: '.min.css'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// These plugins provide necessary tasks.
|
||||
grunt.loadNpmTasks('grunt-gitinfo');
|
||||
grunt.loadNpmTasks('grunt-template');
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-autoprefixer');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', [
|
||||
'gitinfo',
|
||||
'template',
|
||||
'less',
|
||||
'autoprefixer',
|
||||
'cssmin',
|
||||
'concat',
|
||||
'uglify',
|
||||
// 'jshint',
|
||||
'watch'
|
||||
]);
|
||||
|
||||
};
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,97 @@
|
|||
################################################
|
||||
# OpenWrt Makefile for Doodle3D Print3D driver #
|
||||
################################################
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME := doodle3d-client
|
||||
PKG_VERSION := 0.9.3
|
||||
PKG_RELEASE := 1
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/doodle3d-client
|
||||
SECTION:=mods
|
||||
CATEGORY:=Doodle3D
|
||||
TITLE:=Doodle3D web client
|
||||
DEPENDS:=
|
||||
endef
|
||||
|
||||
define Package/doodle3d-client/description
|
||||
This package provides the Doodle3D web client, which interacts with the wifibox package using a REST API.
|
||||
endef
|
||||
|
||||
define Package/doodle3d-client/config
|
||||
config DOODLE3D_CLIENT_MINIFY_JS
|
||||
depends on PACKAGE_doodle3d-client
|
||||
bool "Minify javascript"
|
||||
default y
|
||||
help
|
||||
All javascript files are concatenated into one file; this file enables minification
|
||||
of that file. Disable this to make on-the-fly modifications easier.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) js $(PKG_BUILD_DIR)/
|
||||
$(CP) less $(PKG_BUILD_DIR)/
|
||||
$(CP) www $(PKG_BUILD_DIR)/
|
||||
$(CP) Gruntfile.js $(PKG_BUILD_DIR)/
|
||||
$(CP) README.md $(PKG_BUILD_DIR)/
|
||||
$(CP) lesstocss.sh $(PKG_BUILD_DIR)/
|
||||
$(CP) package.json $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
# We're running grunt in the shared folder, so
|
||||
# grunt can access git info
|
||||
npm install
|
||||
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y)
|
||||
grunt gitinfo template less autoprefixer cssmin concat uglify
|
||||
else
|
||||
grunt gitinfo template less autoprefixer cssmin concat
|
||||
endif
|
||||
# Copy compiled files to build dir
|
||||
$(CP) www $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/doodle3d-client/install
|
||||
|
||||
$(INSTALL_DIR) $(1)/www
|
||||
$(INSTALL_DIR) $(1)/www/filemanager
|
||||
$(INSTALL_DIR) $(1)/www/css
|
||||
$(INSTALL_DIR) $(1)/www/img
|
||||
#$(INSTALL_DIR) $(1)/www/js
|
||||
$(INSTALL_DIR) $(1)/www/js/libs
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/www/favicon* $(1)/www/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/index.html $(1)/www/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/redirect.html $(1)/www/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/404.html $(1)/www/
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/css/styles.min.css $(1)/www/css/
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/www/img/* $(1)/www/img/
|
||||
$(CP) $(PKG_BUILD_DIR)/www/filemanager/* $(1)/www/filemanager/
|
||||
|
||||
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y)
|
||||
$(CP) $(PKG_BUILD_DIR)/www/js/doodle3d-client.min.js $(1)/www/js/
|
||||
else
|
||||
#NOTE: if using a symlink here installation with openwrt make fails
|
||||
# when trying to build with minification after package has been built
|
||||
# without minification (dangling symlink breaks openwrt's final copy command)
|
||||
$(CP) $(PKG_BUILD_DIR)/www/js/doodle3d-client.js $(1)/www/js/doodle3d-client.min.js
|
||||
#$(LN) -s /www/js/doodle3d-client.js $(1)/www/js/doodle3d-client.min.js
|
||||
endif
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/www/js/libs/* $(1)/www/js/libs/
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/www/library $(1)/www/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,doodle3d-client))
|
|
@ -0,0 +1,10 @@
|
|||
Doodle3D uses the following external projects:
|
||||
|
||||
Garden font - Copyright (c) 2012 So-ghislaine - "Garden is a free font for commercial and personal use."
|
||||
Copse font - Copyright (c) 2010 Dan Rhatigan - SIL Open Font License v1.10
|
||||
jQuery - Copyright (c) 2005, 2012 jQuery Foundation, Inc. and other contributors - MIT License
|
||||
jQuery-cookie - Copyright (c) 2011, Klaus Hartl - MIT or GPLv2
|
||||
jQuery-coolfieldset - Copyright (c) 2010 Lucky <bogeyman2007@gmail.com> - GPL
|
||||
jQuery-joyride - Copyright (c) 2013, ZURB - MIT
|
||||
FileSaver - Copyright (c) 2013 Ely Grey - X11/MIT
|
||||
|
14
README.md
|
@ -0,0 +1,14 @@
|
|||
Doodle3D client app
|
||||
===================
|
||||
|
||||
|
||||
# How to build
|
||||
|
||||
## Prerequisites
|
||||
- install npm, the Node.js package manager: `sudo port install npm`
|
||||
- install Grunt: `sudo npm install -g grunt-cli`
|
||||
- run `npm install` in the **project root** to install project dependencies
|
||||
|
||||
## Build
|
||||
- run `grunt` in the project root to to build minified css and js files. By default, it will keep
|
||||
running to automatically rebuild when source files are changed.
|
154
___settings.html
|
@ -1,154 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>settings</title>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
|
||||
<link href="css/settings.css" rel="stylesheet" media="screen">
|
||||
</head>
|
||||
<body>
|
||||
<div class="settingsContainer">
|
||||
<form id="settingsForm">
|
||||
<!--<fieldset>
|
||||
<legend>3D printer</legend>
|
||||
<label for="printerType">Type:</label>
|
||||
<select id="printerType" name="printer.type">
|
||||
<option value="rigidbot">Rigidbot</option>
|
||||
<option value="ultimaker">Ultimaker</option>
|
||||
<option value="makerbot_replicator2">MakerBot Replicator2</option>
|
||||
<option value="makerbot_thingomatic">MakerBot Thing-o-matic</option>
|
||||
<option value="printrbot">Printrbot</option>
|
||||
<option value="bukobot">Bukobot</option>
|
||||
<option value="cartesio">Cartesio</option>
|
||||
<option value="cyrus">Cyrus</option>
|
||||
<option value="delta_rostockmax">Delta RostockMax</option>
|
||||
<option value="deltamaker">Deltamaker</option>
|
||||
<option value="eventorbot">EventorBot</option>
|
||||
<option value="felix">Felix</option>
|
||||
<option value="gigabot">Gigabot</option>
|
||||
<option value="kossel">Kossel</option>
|
||||
<option value="leapfrog_creatr">LeapFrog Creatr</option>
|
||||
<option value="lulzbot_aO_101">LulzBot AO-101</option>
|
||||
<option value="makergear_m2">MakerGear M2</option>
|
||||
<option value="makergear_prusa">MakerGear Prusa</option>
|
||||
<option value="makibox">Makibox</option>
|
||||
<option value="orca_0_3">Orca 0.3</option>
|
||||
<option value="ord_bot_hadron">ORD Bot Hadron</option>
|
||||
<option value="printxel_3d">Printxel 3D</option>
|
||||
<option value="prusa_i3">Prusa I3</option>
|
||||
<option value="prusa_iteration_2">Prusa Iteration 2</option>
|
||||
<option value="rapman">RapMan</option>
|
||||
<option value="reprappro_huxley">RepRapPro Huxley</option>
|
||||
<option value="reprappro_mendel">RepRapPro Mendel</option>
|
||||
<option value="robo_3d_printer">RoBo 3D Printer</option>
|
||||
<option value="shapercube">ShaperCube</option>
|
||||
<option value="tantillus">Tantillus</option>
|
||||
<option value="vision_3d_printer">Vision 3D Printer</option>
|
||||
</select>
|
||||
<br>
|
||||
<label for="printerBaudrate">Baud rate:</label>
|
||||
<select id="printerBaudrate" name="printer.baudrate">
|
||||
<option value="115200">115200 bps</option>
|
||||
<option value="2500000">2500000 bps</option>
|
||||
</select>
|
||||
</fieldset>-->
|
||||
|
||||
<fieldset id="printersettings">
|
||||
<legend>Print settings</legend>
|
||||
<label for="layerHeight">Layer height:</label><input id="layerHeight" type="number" step="0.01" class="small" name="printer.layerHeight">mm<br>
|
||||
<label for="wallThickness">Wall thickness:</label><input id="wallThickness" type="number" step="0.1" class="small" name="printer.wallThickness">mm<br>
|
||||
<label for="filamentThickness">Filament thickness:</label><input id="filamentThickness" step="0.01" type="number" class="small" name="printer.filamentThickness">mm<br>
|
||||
<label for="temperature">Temperature:</label><input id="temperature" type="number" class="small" name="printer.temperature">degrees C<br>
|
||||
<br>
|
||||
<label for="speed">Speed:</label><input id="speed" type="number" name="printer.speed" class="small">mm/s<br>
|
||||
<label for="travelSpeed">Travel speed:</label><input id="travelSpeed" type="number" name="printer.travelSpeed" class="small">mm/s<br>
|
||||
<label for="enableTraveling">Enable traveling:</label><input id="enableTraveling" type="checkbox" name="printer.enableTraveling" value="enableTraveling"><br>
|
||||
<label for="firstLayerSlow">First layer slow:</label><input id="firstLayerSlow" type="checkbox" name="printer.firstLayerSlow" value="firstLayerSlow"><br>
|
||||
<label for="useSubLayers">Use sub-layers*:</label><input id="useSubLayers" type="checkbox" name="printer.useSubLayers" value="firstLayerSlow"><br>
|
||||
<small>* Continuously move platform while printing instead of once per layer</small>
|
||||
<br>
|
||||
<label for="useRetraction">Use retraction:</label><input id="useRetraction" type="checkbox" name="printer.retraction.enabled" value="useRetraction"><br>
|
||||
<label for="retractionAmount">Retraction amount:</label><input id="retractionAmount" type="number" class="small" name="printer.retraction.amount">mm<br>
|
||||
<label for="retractionMinDistance">Retraction min distance:</label><input id="retractionMinDistance" type="number" class="small" name="printer.retraction.minDistance">mm<br>
|
||||
<label for="retractionSpeed">Retraction speed:</label><input id="retractionSpeed" type="number" class="small" name="printer.retraction.speed">mm/s<br>
|
||||
<br>
|
||||
<label for="autoWarmUp">Auto warm-up:</label><input id="autoWarmUp" type="checkbox" name="printer.autoWarmUp" value="autoWarmUp"><br>
|
||||
<label for="autoWarmUpCommand">Auto Warm up command:</label><input id="autoWarmUpCommand" type="text" name="printer.autoWarmUpCommand"><br>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="doodlesettings">
|
||||
<legend>Doodle3D settings</legend>
|
||||
<label for="simplifyMinDistance">Minimal line distance:</label><input id="simplifyMinDistance" type="number" class="small" name="doodle3d.simplify.minDistance">px<br>
|
||||
<label for="maxObjectHeight">Max object height:</label><input id="maxObjectHeight" type="number" class="small" name="printer.maxObjectHeight">mm<br>
|
||||
<label for="screenToMillimeterScale">Pixels to mm scale:</label><input id="screenToMillimeterScale" type="number" step="0.1" class="small" name="printer.screenToMillimeterScale"><br>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Network settings</legend>
|
||||
<label>Connection type:</label>
|
||||
<div>
|
||||
<label for="ap"><input type="radio" name="connectiontype" value="ap" id="ap">Access point mode</label>
|
||||
<label for="client"><input type="radio" name="connectiontype" value="client" id="client">Client mode</label>
|
||||
</div>
|
||||
|
||||
<fieldset id="apSettings">
|
||||
<legend>Access point settings</legend>
|
||||
<label for="ipaddress">Wi-Fi box IP address:</label><input type="text" name="network.ap.address" id="ipaddress"><br>
|
||||
<label for="netmask">Wi-Fi box netmask:</label><input type="text" name="network.ap.netmask" id="netmask"><br>
|
||||
<label for="ssid">Wi-Fi box ssid*:</label><input type="text" class="large" name="network.ap.ssid" id="ssid"> <br>
|
||||
<small>* The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
||||
<input type="button" name="create" value="Create" class="button" id="createAP"/>
|
||||
<span id="apModeState"></span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="clientSettings">
|
||||
<legend>Client mode settings</legend>
|
||||
<label for="network">Network:</label>
|
||||
<select id="network" name="network.client.network">
|
||||
<option value="rigidbot">Fablab Amersfoort</option>
|
||||
<option value="ultimaker">Globe4D</option>
|
||||
</select>
|
||||
<input type="button" name="refresh" value="Refresh" class="button" id="refreshNetworks"/><br>
|
||||
<label for="password" id="passwordLabel">Password:</label><input type="password" name="network.client.password" id="password"><br>
|
||||
<input type="button" name="connect" value="Connect" class="button" id="connectToNetwork"/>
|
||||
<span id="clientModeState"></span>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>GCODE settings</legend>
|
||||
<div class="startgcode_left">
|
||||
<label for="startgcode">Start:</label><br/>
|
||||
<textarea id="startgcode" class="gcode" name="printer.startgcode">
|
||||
</textarea>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<label for="endgcode">End:</label><br/>
|
||||
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
||||
</textarea>
|
||||
</div>
|
||||
<!-- 2013-10-09 replaced by DIV solution (but keeping here in comments temporarily as lookup...)
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="startgcode">Start:</label><br>
|
||||
<textarea id="startgcode" class="gcode" name="printer.startgcode">
|
||||
</textarea>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<label for="endgcode">End:</label><br>
|
||||
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
||||
</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
-->
|
||||
</fieldset>
|
||||
</form><br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,74 +0,0 @@
|
|||
#contentOverlay {
|
||||
background-color: rgba(255, 255, 255, 0.65);
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 1024px;
|
||||
height: 100%;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.popup {
|
||||
background-color: #fff;
|
||||
z-index: 15;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 835px;
|
||||
height: 500px;
|
||||
margin: -250px 0 0 -417.5px;
|
||||
/*padding: 25px;*/
|
||||
|
||||
/*overflow: scroll;*/
|
||||
/*overflow-y: hidden;*/
|
||||
-moz-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
border: 2px solid #222;
|
||||
border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
-webkit-border-radius: 15px;
|
||||
overflow: hidden;
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
#settings header {
|
||||
margin: 25px 25px 0 25px;
|
||||
height: 44px;
|
||||
}
|
||||
#settings div.content {
|
||||
margin: 15px 25px 25px 25px;
|
||||
height: 388px;
|
||||
display: table;
|
||||
}
|
||||
#settings div.content > div {
|
||||
height: 100%;
|
||||
}
|
||||
#settings div.content > div.settings {
|
||||
border: 1px solid rgb(187, 187, 187);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
|
||||
width: 660px;
|
||||
overflow: scroll;
|
||||
max-height: 368px;
|
||||
overflow-x: hidden;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
#settings div.content > div.manipulationBtns {
|
||||
display: table-cell;
|
||||
vertical-align: bottom;
|
||||
width: 125px;
|
||||
|
||||
}
|
||||
#settings div.content .btnOK {
|
||||
width: 85px;
|
||||
height: 86px;
|
||||
background: url('../img/buttons/btnOk_settings.png') no-repeat;
|
||||
margin: 0 0 0 10px;
|
||||
cursor: pointer;
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
form {
|
||||
margin: 10px;
|
||||
max-width: 600px;
|
||||
}
|
||||
form input {
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
body,th,td {
|
||||
font-family: Helvetica, Arial, "Nimbus Sans L", sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
.settingsContainer {
|
||||
position:relative;
|
||||
/*min-width: 370px;*/
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/*form#settingsForm {*/
|
||||
/*width: 100% auto;*/
|
||||
/*}*/
|
||||
form fieldset {
|
||||
max-width: 600px;
|
||||
border: 1px solid rgb(187, 187, 187);
|
||||
border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
padding: 8px;
|
||||
/*padding-right: 8px;*/
|
||||
}
|
||||
form fieldset fieldset{
|
||||
max-width: 580px;
|
||||
margin: 15px 0 5px 0;
|
||||
clear: left;
|
||||
float: left;
|
||||
}
|
||||
form fieldset legend {
|
||||
margin-left: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
form label {
|
||||
min-width: 150px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 1px 0 0 0;
|
||||
clear: left;
|
||||
}
|
||||
form div {
|
||||
float: left;
|
||||
}
|
||||
form input[type="text"], form input[type="number"], form input[type="password"] {
|
||||
border: 1px solid rgb(144, 192, 255);
|
||||
margin-right: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
form input[type="text"].small, form input[type="number"].small, form input[type="password"].small {
|
||||
width: 50px;
|
||||
}
|
||||
form input[type="text"].large, form input[type="number"].large, form input[type="password"].large {
|
||||
width: 250px;
|
||||
}
|
||||
form input[type="radio"] {
|
||||
margin: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
form textarea {
|
||||
border: 1px solid rgb(144, 192, 255);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
form .startgcode_left {
|
||||
float:left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
form textarea.gcode {
|
||||
width: 252px;
|
||||
/*max-width: 262px;*/
|
||||
/*min-width: 200px;*/
|
||||
height: 150px;
|
||||
}
|
||||
form small {
|
||||
margin: 3px 0 0 0;
|
||||
display: block;
|
||||
clear: left;
|
||||
}
|
||||
form .button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form #passwordLabel, form #password {
|
||||
display: none;
|
||||
}
|
809
css/styles.css
|
@ -1,809 +0,0 @@
|
|||
/*
|
||||
|
||||
GLOBAL CONTAINER
|
||||
|
||||
*/
|
||||
body {
|
||||
background-color: #fcfcfc;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; /* disable cut copy paste */
|
||||
/* disable cut copy paste */
|
||||
overflow: hidden; /* This chops off any overhanging divs */
|
||||
}
|
||||
|
||||
img {
|
||||
z-index: 5; /*pointer-events: none;
|
||||
*/
|
||||
/*-webkit-touch-callout: none;
|
||||
*/
|
||||
/*disable callout, image save panel */
|
||||
/*-webkit-tap-highlight-color: transparent;
|
||||
*/
|
||||
/* "turn off" link highlight */
|
||||
}
|
||||
|
||||
/* http://stackoverflow.com/questions/5348092/prevent-default-press-but-not-default-drag-in-ios-mobilesafari */
|
||||
.btn {
|
||||
background-repeat: no-repeat; /* -webkit-user-select: none;
|
||||
*/
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#landscape {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
max-width: 1024px;
|
||||
max-height: 768px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
margin: 0px auto;
|
||||
outline: 2px solid #5e8c71;
|
||||
|
||||
-webkit-box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
|
||||
box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
|
||||
}
|
||||
|
||||
#portrait {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bgContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bgTop,.bgMiddle,.bgBottom {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
|
||||
-webkit-transition: opacity .35s linear;
|
||||
-moz-transition: opacity .35s linear;
|
||||
-o-transition: opacity .35s linear;
|
||||
-ms-transition: opacity .35s linear;
|
||||
transition: opacity .35s linear;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
z-index: -5;
|
||||
}
|
||||
|
||||
.bgTop {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.bgMiddle {
|
||||
top: 30%;
|
||||
}
|
||||
|
||||
.bgBottom {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CENTER PANEL
|
||||
|
||||
*/
|
||||
.centerpanel {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -33%;
|
||||
width: 66%;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.logopanel {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
position: relative;
|
||||
top: 15%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px auto;
|
||||
max-width: 399px;
|
||||
height: 139px;
|
||||
background: url('../img/logo/logo_full.png') no-repeat center center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#verticalShapes {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 15px;
|
||||
margin-right: -8.5%;
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
#verticalShapes > div {
|
||||
border: 2px solid #333;
|
||||
border-radius: 0px 5px 5px 0px;
|
||||
margin-top: 4px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#verticalShapes > div img.verticalshape {
|
||||
width: 100%;
|
||||
max-width: 50px;
|
||||
height: auto;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.drawareacontainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 65%;
|
||||
background-color: #fff;
|
||||
border: 4px solid #000;
|
||||
border-radius: 15px;
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#canvasContainers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mycanvasContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 78%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#mycanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-right: 2px solid #333;
|
||||
}
|
||||
|
||||
#previewContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 22%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#preview {
|
||||
min-width: 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* DEBUG THING */
|
||||
#preview_tmp {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 500;
|
||||
border: 1px solid #f80;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bottompanel {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
/*
|
||||
DOODLE UP/DOWN/LEFT/RIGHT buttons
|
||||
*/
|
||||
.manipulationBtns {
|
||||
margin: 2px 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-width: 340px;
|
||||
max-height: 70px;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.manipulationBtn {
|
||||
width: 45%;
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#btnsUpDown {
|
||||
float: left;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
#btnsUpDown > div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnsTurnLeftRight {
|
||||
float: right;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
#btnsTurnLeftRight > div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnMoveUp {
|
||||
max-width: 65px;
|
||||
}
|
||||
|
||||
#btnMoveDown {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
#btnTwistLeft {
|
||||
max-width: 59px;
|
||||
}
|
||||
|
||||
#btnTwistRight {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
/*
|
||||
HEIGHT-related RESPONSIVE STUFF
|
||||
*/
|
||||
@media screen and (max-height: 700px) {
|
||||
.logopanel {
|
||||
height: 22%;
|
||||
}
|
||||
|
||||
.doodlecontainer {
|
||||
height: 68%;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
top: 25%;
|
||||
max-width: 399px;
|
||||
height: 74px;
|
||||
background-image: url('../img/logo/logo_small.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 655px) {
|
||||
.bgMiddle {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 525px) {
|
||||
.d3dlogo {
|
||||
top: 20%;
|
||||
height: 57px;
|
||||
max-width: 307px;
|
||||
background-image: url('../img/logo/logo_smaller.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 375px) {
|
||||
.d3dlogo {
|
||||
height: 40px;
|
||||
max-width: 216px;
|
||||
background-image: url('../img/logo/logo_smallest.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LEFT PANEL
|
||||
|
||||
*/
|
||||
.leftpanel {
|
||||
position: absolute;
|
||||
width: 17%; /* background-color: rgba(67, 204, 67, 0.4);
|
||||
*/
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.btnNew {
|
||||
margin: 5% 0% 1% 5%;
|
||||
width: 100%;
|
||||
max-width: 180px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnsPrevNext {
|
||||
margin: 1% 7%;
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
.btnPrevious {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnNext {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.btnSave {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnOops {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
RIGHT PANEL
|
||||
|
||||
*/
|
||||
.rightpanel {
|
||||
position: absolute;
|
||||
width: 17%; /* background-color: rgba(255, 0, 254, 0.4);
|
||||
*/
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.btnPrint {
|
||||
margin: 1% 5% 5% 0%;
|
||||
width: 100%;
|
||||
max-width: 163px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.btnStop {
|
||||
margin: 5% 10% 1% 5%;
|
||||
float: right;
|
||||
width: 90%;
|
||||
max-width: 98px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnsSettingsInfo {
|
||||
position: absolute;
|
||||
bottom: 25px;
|
||||
right: 5px;
|
||||
width: 80%;
|
||||
margin: 1% 5%;
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
.btnInfo {
|
||||
width: 40%;
|
||||
max-width: 53px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnSettings {
|
||||
width: 40%;
|
||||
max-width: 53px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
PRINT PROGRESS DISPLAY
|
||||
|
||||
*/
|
||||
#printProgressContainer {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 370px;
|
||||
width: 110px;
|
||||
margin: 5px 0px;
|
||||
font-weight: bold;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#progressbarContainer {
|
||||
margin: 3px 0px;
|
||||
width: inherit;
|
||||
height: 20px;
|
||||
background-color: #fff;
|
||||
border: 2px solid #333;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progressAmount {
|
||||
margin: 0px 5px;
|
||||
}
|
||||
|
||||
#progressbar {
|
||||
position: relative; /*margin-bottom: -20px;
|
||||
*/
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background-color: #4c4;
|
||||
border: 0px solid #f0f;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
THERMOMETER
|
||||
|
||||
*/
|
||||
#thermometerContainer {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
top: 370px;
|
||||
}
|
||||
|
||||
#thermometerCanvas {
|
||||
/*background: #59b2b8;
|
||||
*/
|
||||
/*zoom: 2;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
under all the above styles w.r.t. the cascading effect
|
||||
*/
|
||||
.disabled {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
|
||||
filter: alpha(opacity=30);
|
||||
opacity: 0.3;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#btnStop.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
REST
|
||||
|
||||
*/
|
||||
/* CLEARFIX */
|
||||
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
|
||||
.clearfix:before,.clearfix:after {
|
||||
content: " "; /* 1 */
|
||||
display: table; /* 2 */
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* For IE 6/7 only*/
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
SETTINGS POPUP
|
||||
|
||||
*/
|
||||
#contentOverlay {
|
||||
background-color: rgba(255, 255, 255, 0.65);
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#contentOverlay #settings {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 15;
|
||||
max-width: 775px;
|
||||
max-height: 540px;
|
||||
width: 80%;
|
||||
height: 75%;
|
||||
margin: 7% 8%;
|
||||
|
||||
-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
border: 2px solid #222;
|
||||
border-radius: 15px;
|
||||
padding: 2%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel {
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel .settingsLabelContainer {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 1%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel .settingsLabelContainer .settingsLabelImg {
|
||||
width: 45%;
|
||||
max-width: 373px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel {
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .settingsContainer {
|
||||
float: left;
|
||||
width: 83%;
|
||||
height: 98%;
|
||||
margin: .5%;
|
||||
|
||||
-ms-overflow-y: scroll;
|
||||
overflow-y: scroll;
|
||||
border: 1px solid #bbbbbb;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .btnContainer {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
position: relative;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .btnContainer > .btnOK {
|
||||
position: absolute;
|
||||
bottom: 3%;
|
||||
right: 7%;
|
||||
max-width: 85px;
|
||||
min-width: 42px;
|
||||
width: 88%;
|
||||
height: auto;
|
||||
margin: 0 2% 2% 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px),only screen and (max-width: 720px) and (min-device-pixel-ratio: 1.5),only screen and (max-width: 720px) and (-webkit-min-device-pixel-ratio: 1.5) {
|
||||
/*
|
||||
TOP LOGO
|
||||
*/
|
||||
.centerpanel {
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
width: 100%; /* background-color: rgba(0, 135, 255, 0.4);
|
||||
*/
|
||||
}
|
||||
|
||||
.logopanel {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
top: 0;
|
||||
height: 40px;
|
||||
max-width: 216px;
|
||||
background-image: url('../img/logo/logo_smallest.png');
|
||||
}
|
||||
|
||||
.doodlecontainer {
|
||||
/* position: absolute;
|
||||
*/
|
||||
height: 85%;
|
||||
}
|
||||
|
||||
/*.bottompanel {
|
||||
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
LEFT
|
||||
*/
|
||||
.leftpanel {
|
||||
width: 100px;
|
||||
background-color: #fff;
|
||||
z-index: 50;
|
||||
|
||||
-webkit-transition: left 0.3s ease-out;
|
||||
-moz-transition: left 0.3s ease-out;
|
||||
-o-transition: left 0.3s ease-out;
|
||||
-ms-transition: left 0.3s ease-out;
|
||||
transition: left 0.3s ease-out;
|
||||
}
|
||||
|
||||
.hideleft {
|
||||
left: -101px;
|
||||
}
|
||||
|
||||
.shadowright {
|
||||
-webkit-box-shadow: 2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
box-shadow: 2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
}
|
||||
|
||||
.btnNew {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.btnSave {
|
||||
margin-left: 9%;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.btnOops {
|
||||
margin-left: 6%;
|
||||
width: 71%;
|
||||
}
|
||||
|
||||
/*
|
||||
RIGHT
|
||||
*/
|
||||
.rightpanel {
|
||||
width: 100px;
|
||||
background-color: #fff;
|
||||
z-index: 50;
|
||||
|
||||
-webkit-transition: right 0.3s ease-out;
|
||||
-moz-transition: right 0.3s ease-out;
|
||||
-o-transition: right 0.3s ease-out;
|
||||
-ms-transition: right 0.3s ease-out;
|
||||
transition: right 0.3s ease-out;
|
||||
}
|
||||
|
||||
.hideright {
|
||||
right: -101px;
|
||||
}
|
||||
|
||||
.shadowleft {
|
||||
-webkit-box-shadow: -2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
box-shadow: -2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
}
|
||||
|
||||
.btnPrint {
|
||||
margin: 1% 5% 5% 5%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.btnStop {
|
||||
margin: 5% 6% 1% 5%;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
/*
|
||||
REST
|
||||
*/
|
||||
.sidebutton {
|
||||
display: block;
|
||||
position: absolute; /* top: 50%;
|
||||
*/
|
||||
/* margin-top: -20px;
|
||||
*/
|
||||
top: 0px; /*float: right;
|
||||
*/
|
||||
width: 25px;
|
||||
height: 38px;
|
||||
border: 1px solid #808;
|
||||
background: url('../img/arrows.png') no-repeat;
|
||||
background-color: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebutton:active {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
.leftpanel .sidebutton {
|
||||
right: -27px;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
.rightpanel .sidebutton {
|
||||
left: -27px;
|
||||
background-position: -25px 0px;
|
||||
}
|
||||
|
||||
.sidebuttonin:active {
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.leftpanel .sidebuttonin {
|
||||
background-color: #ccc;
|
||||
background-position: -25px 0px;
|
||||
}
|
||||
|
||||
.rightpanel .sidebuttonin {
|
||||
background-color: #ccc;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
SETTINGS POPUP -MOBILE
|
||||
|
||||
*/
|
||||
#contentOverlay {
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
#contentOverlay #settings {
|
||||
width: 87%;
|
||||
height: 82%;
|
||||
margin: 6% 4%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings > .right {
|
||||
width: 14%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (orientation: portrait) {
|
||||
#landscape {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#portrait {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.vertImage {
|
||||
margin: 0px;
|
||||
padding: 0px; /*border: 2px solid #f0f;
|
||||
*/
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto; /* for ie9 */
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1785.8772"
|
||||
height="37.343998"
|
||||
id="svg3245"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="New document 9">
|
||||
<defs
|
||||
id="defs3247" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.66125533"
|
||||
inkscape:cx="885.47012"
|
||||
inkscape:cy="79.926821"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1670"
|
||||
inkscape:window-height="821"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3250">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(635.23282,-279.42656)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:35.2932663px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="-638.04181"
|
||||
y="220.68825"
|
||||
id="text3253"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3255"
|
||||
x="-638.04181"
|
||||
y="220.68825" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="-638.04181"
|
||||
y="264.80484"
|
||||
id="tspan3257"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Copse;-inkscape-font-specification:Copse" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="-638.04181"
|
||||
y="308.44699"
|
||||
id="tspan3259"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Copse;-inkscape-font-specification:Copse">!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="-638.04181"
|
||||
y="352.56357"
|
||||
id="tspan3261"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Copse;-inkscape-font-specification:Copse" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="-638.04181"
|
||||
y="396.68018"
|
||||
id="tspan3263"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Copse;-inkscape-font-specification:Copse" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Times New Roman;-inkscape-font-specification:Times New Roman"
|
||||
x="488.13605"
|
||||
y="59.544075"
|
||||
id="text3016"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3018"
|
||||
x="488.13605"
|
||||
y="59.544075" /></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.9 KiB |
BIN
img/icon.png
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 5.6 KiB |
137
index.html
|
@ -1,137 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doodle3D</title>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<link rel="icon" type="image/ico" href="favicon_alt.ico"/>
|
||||
<link href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" rel="apple-touch-icon-precomposed" sizes="144x144" />
|
||||
|
||||
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
|
||||
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||
<link href="css/debug.css" rel="stylesheet" media="screen">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landscape" class="clearfix">
|
||||
|
||||
<!-- background images -->
|
||||
<div class="bgContainer">
|
||||
<img class="bgTop" src="img/bg_top.png" />
|
||||
<img class="bgMiddle" src="img/bg_middle.png" />
|
||||
<img class="bgBottom" src="img/bg_bottom.png" />
|
||||
</div>
|
||||
|
||||
<!-- left panel -->
|
||||
<div class="leftpanel shadowright">
|
||||
<div class='sidebutton shadowright'></div>
|
||||
<img class="btnNew btn" src="img/buttons/btnNew.png" /><br/>
|
||||
<div class="btnsPrevNext">
|
||||
<img class="btnPrevious btn" src="img/buttons/btnLeft.png">
|
||||
<img class="btnNext btn" src="img/buttons/btnRight.png">
|
||||
</div>
|
||||
<img class="btnSave btn" src="img/buttons/btnSave.png" /><br/>
|
||||
<img class="btnOops btn" src="img/buttons/btnOops.png" /><br/>
|
||||
</div>
|
||||
|
||||
<!-- right panel -->
|
||||
<div class="rightpanel shadowleft">
|
||||
<div class='sidebutton shadowleft'></div>
|
||||
<img class="btnPrint btn" src="img/buttons/btnPrint.png" /><br/>
|
||||
<img class="btnStop btn disabled" src="img/buttons/btnStop.png" /><br/>
|
||||
<!-- not now
|
||||
<div id="printProgressContainer">
|
||||
<label for="progressbarContainer">Progress:</label><span class="progressAmount">0%</span>
|
||||
<div id="progressbarContainer">
|
||||
<div id="progressbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div id="thermometerContainer">
|
||||
<canvas id="thermometerCanvas" width="100" height="125"></canvas>
|
||||
</div>
|
||||
<div class="btnsSettingsInfo">
|
||||
<img class="btnSettings btn" src="img/buttons/btnSettings.png">
|
||||
<img class="btnInfo btn" src="img/buttons/btnInfo.png">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- center panel -->
|
||||
<div class="centerpanel">
|
||||
<div class="logopanel">
|
||||
<div class="d3dlogo" onclick="location.reload()"></div>
|
||||
</div>
|
||||
<div class="drawareacontainer">
|
||||
<div id="canvasContainers">
|
||||
<div id="mycanvasContainer">
|
||||
<canvas id="mycanvas"></canvas>
|
||||
</div>
|
||||
<div id="previewContainer">
|
||||
<canvas id="preview"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<canvas id="preview_tmp"></canvas>
|
||||
<div id="verticalShapes">
|
||||
<div><img class="verticalshape straight" src="img/vertical_shape_icons/straight.png" /></div>
|
||||
<div><img class="verticalshape diverging" src="img/vertical_shape_icons/diverging.png" /></div>
|
||||
<div><img class="verticalshape converging" src="img/vertical_shape_icons/converging.png" /></div>
|
||||
<div><img class="verticalshape sinus" src="img/vertical_shape_icons/sinus.png" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottompanel">
|
||||
<div class="manipulationBtns clearfix">
|
||||
<div id="btnsUpDown">
|
||||
<img class="manipulationBtn" id="btnMoveUp" src="img/buttons/btnUp.png" />
|
||||
<img class="manipulationBtn" id="btnMoveDown" src="img/buttons/btnDown.png" />
|
||||
</div>
|
||||
<div id="btnsTurnLeftRight">
|
||||
<img class="manipulationBtn" id="btnTwistLeft" src="img/buttons/btnTurnLeft.png" />
|
||||
<img class="manipulationBtn" id="btnTwistRight" src="img/buttons/btnTurnRight.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="debug_textArea">
|
||||
<textarea rows="5" cols="60" id="textdump"></textarea>
|
||||
</div>
|
||||
<div id="debug_display">
|
||||
</div>
|
||||
<div id="contentOverlay">
|
||||
<div id="settings">
|
||||
<div class="toppanel">
|
||||
<div class="settingsLabelContainer">
|
||||
<img class="settingsLabelImg" src="img/settings_lable.png" alt="settings" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottompanel">
|
||||
<div class="settingsContainer"></div>
|
||||
<div class="btnContainer">
|
||||
<img src="img/buttons/btnOk_settings.png" class="btnOK" alt="settings"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="portrait">
|
||||
<img class="vertImage" src="img/bg_vertical2.png"/>
|
||||
</div>
|
||||
<script src="js/libs/jquery-1.8.3.min.js"></script>
|
||||
<script src="js/SettingsWindow.js"></script>
|
||||
<script src="js/d3dServerInterfacing.js"></script>
|
||||
<script src="js/verticalShapes.js"></script>
|
||||
<script src="js/buttonbehaviors.js"></script>
|
||||
<script src="js/canvasDrawing.js"></script>
|
||||
<script src="js/previewRendering.js"></script>
|
||||
<script src="js/gcodeGenerating.js"></script>
|
||||
<script src="js/init_layout.js"></script>
|
||||
<script src="js/Printer.js"></script>
|
||||
<script src="js/Thermometer.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/sidebar.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,41 @@
|
|||
//var shapeResolution=3;
|
||||
var shapePopup;
|
||||
|
||||
function initScanDialog() {
|
||||
scanPopup = new Popup($("#popupScan"), $("#popupMask"));
|
||||
$("#btnScanOk").on("onButtonClick", onBtnScanOk);
|
||||
$("#btnCloseScan").on("onButtonClick", onBtnCloseScan);
|
||||
}
|
||||
|
||||
function onBtnCloseScan() {
|
||||
$('#imgGuide').hide();
|
||||
$('#btnCloseScan').hide();
|
||||
}
|
||||
|
||||
function onBtnScanOk() {
|
||||
scanPopup.commit();
|
||||
}
|
||||
|
||||
function showScanDialog() {
|
||||
scanPopup.open();
|
||||
}
|
||||
|
||||
function readURL(input) {
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function (e) {
|
||||
$('#imgGuide').attr('src', e.target.result);
|
||||
$('#imgGuide').show();
|
||||
$('#btnCloseScan').show();
|
||||
scanPopup.commit();
|
||||
}
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
$("#fileScan").change(function(){
|
||||
readURL(this);
|
||||
});
|
|
@ -0,0 +1,78 @@
|
|||
var shapeResolution=3;
|
||||
var shapePopup;
|
||||
|
||||
function initShapeDialog() {
|
||||
shapePopup = new Popup($("#popupShape"), $("#popupMask"));
|
||||
$("#btnShapeOk").on("onButtonClick", shapePopup.commit);
|
||||
$("#btnShapeCancel").on("onButtonClick", shapePopup.cancel);
|
||||
$("#popupShape").bind("onPopupCancel", onShapeCancel);
|
||||
$("#popupShape").bind("onPopupCommit", onShapeOk);
|
||||
|
||||
$("#btnShapePlus").on("onButtonHold",onShapePlus);
|
||||
$("#btnShapeMin").on("onButtonHold",onShapeMin);
|
||||
updateShapePreview();
|
||||
}
|
||||
|
||||
function showShapeDialog() {
|
||||
shapePopup.open();
|
||||
}
|
||||
|
||||
function onShapeCancel() {
|
||||
}
|
||||
|
||||
function onShapeOk() {
|
||||
var res = shapeResolution;
|
||||
|
||||
if (res!=undefined) {
|
||||
if (isNaN(res)) res=3;
|
||||
if (res<2) res=2;
|
||||
if (res>100) res=100;
|
||||
drawCircle(canvasWidth/2,canvasHeight/2,80,res);
|
||||
}
|
||||
}
|
||||
|
||||
function onShapePlus() {
|
||||
shapeResolution++;
|
||||
if (shapeResolution>50) shapeResolution=50;
|
||||
updateShapePreview();
|
||||
}
|
||||
|
||||
function onShapeMin() {
|
||||
shapeResolution--;
|
||||
if (shapeResolution<2) shapeResolution=2;
|
||||
updateShapePreview();
|
||||
}
|
||||
|
||||
function updateShapePreview() {
|
||||
$(".lblShapeResolution").text(shapeResolution + " sides");
|
||||
|
||||
var canvas = $("#shapePreview")[0];
|
||||
var c = canvas.getContext('2d');
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
//console.log(w,h);
|
||||
var r = w/2 - 20;
|
||||
var x0 = w/2;
|
||||
var y0 = h/2;
|
||||
var res = shapeResolution;
|
||||
var step = Math.PI * 2.0 / res;
|
||||
|
||||
c.save();
|
||||
c.clearRect(0,0,canvas.width, canvas.height);
|
||||
c.restore();
|
||||
c.beginPath();
|
||||
for (var a=0; a<Math.PI*2; a+=step) {
|
||||
var x = Math.sin(a+Math.PI) * r + x0;
|
||||
var y = Math.cos(a+Math.PI) * r + y0;
|
||||
if (a==0) c.moveTo(x,y);
|
||||
else c.lineTo(x,y);
|
||||
}
|
||||
//close shape
|
||||
var x = Math.sin(0+Math.PI) * r + x0;
|
||||
var y = Math.cos(0+Math.PI) * r + y0;
|
||||
c.lineTo(x,y);
|
||||
|
||||
//draw shape
|
||||
c.lineWidth = 2;
|
||||
c.stroke();
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
// prototype inheritance
|
||||
// http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
|
||||
Button.prototype = new jQuery();
|
||||
function Button() {
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
var _clickEnabled = true;
|
||||
var _downTimerFPS = 20;
|
||||
var _timer;
|
||||
var _x,_y;
|
||||
var _isDown = false;
|
||||
var _self = this;
|
||||
|
||||
// call jQuery constuctor
|
||||
// http://blog.santoshrajan.com/2008/10/what-john-resig-did-not-tell-you.html
|
||||
this.constructor.prototype.init.apply(this, arguments);
|
||||
|
||||
// prevent multiple event handlers etc
|
||||
// make sure you do a more general conversion last
|
||||
if(this.data("isButton")) {
|
||||
return;
|
||||
} else {
|
||||
this.data("isButton",true);
|
||||
}
|
||||
|
||||
this.enable = function() {
|
||||
if(_self.enabled === true) { return; }
|
||||
_self.removeClass("disabled");
|
||||
_self.enabled = true;
|
||||
};
|
||||
this.disable = function() {
|
||||
if(_self.enabled === false) { return; }
|
||||
_self.addClass("disabled");
|
||||
_self.enabled = false;
|
||||
};
|
||||
// if the element starts with a disable class, we properly disable it
|
||||
if(this.hasClass("disabled")) {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
function updateCursor(e) {
|
||||
// retrieve cursor position relative to element
|
||||
if (e.offsetX !== undefined) {
|
||||
_x = e.offsetX;
|
||||
_y = e.offsetY;
|
||||
} else {
|
||||
var offset = _self.offset();
|
||||
if(e.pageX !== undefined) {
|
||||
// http://www.quirksmode.org/mobile/tableViewport_desktop.html#t11
|
||||
_x = e.pageX - offset.left;
|
||||
_y = e.pageY - offset.top;
|
||||
} else if(e.originalEvent !== undefined && e.originalEvent.pageX !== undefined) {
|
||||
//http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/
|
||||
_x = e.originalEvent.pageX - offset.left;
|
||||
_y = e.originalEvent.pageY - offset.top;
|
||||
}
|
||||
|
||||
//android+chrome-specific hack
|
||||
if (e.originalEvent.changedTouches !== undefined) {
|
||||
_x = e.originalEvent.changedTouches[0].pageX - offset.left;
|
||||
_y = e.originalEvent.changedTouches[0].pageY - offset.top;
|
||||
}
|
||||
}
|
||||
}
|
||||
function startDownTimer() {
|
||||
if (_timer === undefined) {
|
||||
_timer = setInterval(onDownTimerInterval, 1000/_downTimerFPS);
|
||||
_isDown = true;
|
||||
}
|
||||
}
|
||||
function stopDownTimer() {
|
||||
clearInterval(_timer);
|
||||
_timer = undefined;
|
||||
_isDown = false;
|
||||
// _x = undefined;
|
||||
// _y = undefined;
|
||||
}
|
||||
function onDownTimerInterval() {
|
||||
if(!_self.enabled) { return; }
|
||||
if (_x !== undefined && _y !== undefined) {
|
||||
_self.trigger("onButtonHold",{x:_x,y:_y});
|
||||
} else {
|
||||
console.log("Button: warning... _x or _y not set...");
|
||||
}
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
$(document).mouseup(function(e) {
|
||||
stopDownTimer();
|
||||
});
|
||||
this.on("touchstart", function(e) {
|
||||
if(!_self.enabled) { return; }
|
||||
_clickEnabled = false;
|
||||
updateCursor(e);
|
||||
startDownTimer();
|
||||
_self.trigger("onButtonClick",{x:_x,y:_y});
|
||||
e.preventDefault();
|
||||
});
|
||||
this.on("touchend", function(e) {
|
||||
updateCursor(e);
|
||||
stopDownTimer();
|
||||
});
|
||||
this.on("touchmove", function(e) {
|
||||
if(!_self.enabled) { return; }
|
||||
updateCursor(e);
|
||||
startDownTimer();
|
||||
});
|
||||
this.mousedown(function(e) {
|
||||
if(!_self.enabled) { return; }
|
||||
updateCursor(e);
|
||||
startDownTimer();
|
||||
});
|
||||
this.mouseup(function(e) {
|
||||
updateCursor(e);
|
||||
stopDownTimer();
|
||||
});
|
||||
this.mousemove(function(e) {
|
||||
if(!_self.enabled) { return; }
|
||||
updateCursor(e);
|
||||
//if (_isDown) mousedrag(e);
|
||||
});
|
||||
//this.mousedrag(function(e) {
|
||||
// updateCursor(e);
|
||||
//});
|
||||
this.contextmenu(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
this.click(function(e) {
|
||||
if(!_self.enabled || !_clickEnabled) { return; }
|
||||
updateCursor(e);
|
||||
stopDownTimer();
|
||||
_self.trigger("onButtonClick",{x:_x,y:_y});
|
||||
});
|
||||
}
|
||||
|
||||
// to work with multiple objects we need a jQuery plugin
|
||||
$.fn.Button = function() {
|
||||
return $(this).each(function(){
|
||||
new Button(this);
|
||||
});
|
||||
};
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var grandTour;
|
||||
function GrandTour(_name) {
|
||||
//console.log("GrandTour");
|
||||
this.tour = "";
|
||||
this.name = _name;
|
||||
this.active = false;
|
||||
var self = this;
|
||||
|
||||
this.init = function() {
|
||||
//console.log("GrandTour >> f:init()");
|
||||
|
||||
this.tour = function() {
|
||||
$('#help_d3dIntro').joyride({
|
||||
autoStart: false,
|
||||
modal: true,
|
||||
expose: true,
|
||||
'tipAdjustmentX': 15,
|
||||
'tipAdjustmentY': 15,
|
||||
'tipLocation': 'bottom', // 'top' or 'bottom' in relation to parent
|
||||
'nubPosition': 'auto', // override on a per tooltip bases
|
||||
'scrollSpeed': 300, // Page scrolling speed in ms
|
||||
// 'timer': 2000, // 0 = off, all other numbers = time(ms)
|
||||
// 'startTimerOnClick': true, // true/false to start timer on first click
|
||||
'nextButton': true, // true/false for next button visibility
|
||||
'tipAnimation': 'fade', // 'pop' or 'fade' in each tip
|
||||
// 'pauseAfter': [], // array of indexes where to pause the tour after
|
||||
'tipAnimationFadeSpeed': 350, // if 'fade'- speed in ms of transition
|
||||
// 'cookieMonster': true, // true/false for whether cookies are used
|
||||
// 'cookieDomain': false, // set to false or yoursite.com
|
||||
// 'cookieName': 'Doodle3DFirstTime', // choose your own cookie name
|
||||
// 'localStorage': true, //
|
||||
// 'localStorageKey': 'Doodle3DFirstTime', // choose your own cookie name
|
||||
'preRideCallback' : self.preRideCallback,
|
||||
'preStepCallback': self.preStepCallback, // A method to call before each step
|
||||
'postStepCallback': self.postStepCallback, // A method to call after each step
|
||||
'postRideCallback': self.postRideCallback // a method to call once the tour closes
|
||||
});
|
||||
};
|
||||
this.tour();
|
||||
};
|
||||
|
||||
this.preRideCallback = function(index, tip) {
|
||||
//console.log("GrandTour >> f:preRideCallback() >> index: " + index);
|
||||
if (index == 0 && $.cookie("Doodle3DFirstTime") == "ridden") {
|
||||
//console.log("GrandTour >> f:preRideCallback() >> we've been here before...");
|
||||
|
||||
if ($.cookie("grandTourFinished")) {
|
||||
// grand tour was previously finished (eh.. is that useful?)
|
||||
|
||||
// executing this 3 times because there doesn't seem to be a 'go to step X' method
|
||||
// $(this).joyride('set_li', false);
|
||||
$(this).joyride('set_li', false);
|
||||
// $(this).joyride('set_li', false);
|
||||
} else {
|
||||
$(this).joyride('set_li', false);
|
||||
}
|
||||
}
|
||||
|
||||
// Overrule printer to tour mode, pausing status updates
|
||||
printer.overruleState(Printer.TOUR_STATE);
|
||||
|
||||
// bring up thermometer and progressbar to explain them
|
||||
thermometer.show();
|
||||
progressbar.show();
|
||||
message.hide();
|
||||
};
|
||||
this.preStepCallback = function(index, tip) {
|
||||
// console.log("GrandTour >> f:preStepCallback() >> index: " + index);
|
||||
// console.log("GrandTour >> f:preStepCallback() >> tip: " , tip);
|
||||
// console.log("GrandTour >> f:preStepCallback() >> $(this): " , $(this));
|
||||
// console.log("GrandTour >> f:preStepCallback() >> tipsettings: " , $(this)[0].tipSettings);
|
||||
|
||||
var dataset = $(this)[0].$li[0].dataset;
|
||||
if (dataset.action != undefined) {
|
||||
switch (dataset.action) {
|
||||
case "showMessage":
|
||||
//console.log(" action: showMessage");
|
||||
message.set("This is a status message...", Message.NOTICE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
this.postStepCallback = function(index, tip) {
|
||||
//console.log("GrandTour >> f:postStepCallback() >> index: " + index);
|
||||
// var dataset = $(this)[0].$li[0].dataset;
|
||||
};
|
||||
this.postRideCallback = function(index, tip) {
|
||||
// console.log("GrandTour >> f:postRideCallback() >> index: " + index + ", self.active: " + self.active);
|
||||
// console.log("GrandTour >> f:postRideCallback() >> this: " , self);
|
||||
|
||||
self.active = false;
|
||||
|
||||
$(document).trigger(helpTours.TOURFINISHED, self.name);
|
||||
|
||||
// hide the elements which were summoned for the purposes of the tour
|
||||
// thermometer.hide();
|
||||
// progressbar.hide();
|
||||
// message.hide();
|
||||
|
||||
// after seeing the grand tour for the first time ever, set cookie 'Doodle3DFirstTime' to true
|
||||
if (!$.cookie("Doodle3DFirstTime")) {
|
||||
$.cookie("Doodle3DFirstTime", 'ridden', { expires: 365, domain: false, path: '/' });
|
||||
}
|
||||
|
||||
if (index < $(this)[0].$tip_content.length - 1) {
|
||||
//console.log("GrandTour >> f:postRideCallback() >> tour terminated before its true end");
|
||||
// tour wasn't finished
|
||||
|
||||
// tour was ended prematurely. For only the first few visits, nag the user about being able to revisit the tour..
|
||||
if (parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) {
|
||||
helpTours.startTour(helpTours.INFOREMINDER, helpTours);
|
||||
}
|
||||
// infoReminderTour.start();
|
||||
} else {
|
||||
// tour was finished
|
||||
//console.log("GrandTour >> f:postRideCallback() >> tour ended at its true end");
|
||||
// we should be at the end...
|
||||
if (!$.cookie("grandTourFinished") && parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) {
|
||||
helpTours.startTour(helpTours.INFOREMINDER, helpTours);
|
||||
}
|
||||
$.cookie("grandTourFinished", 'yes', { expires: 365, domain: false, path: '/' });
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.start = function() {
|
||||
//console.log("GrandTour >> f:start() >> this: " , this);
|
||||
this.active = true;
|
||||
$(window).joyride('restart');
|
||||
// self.tour();
|
||||
};
|
||||
}
|
||||
|
||||
var infoReminderTour;
|
||||
function InfoReminderTour(_name) {
|
||||
//console.log("InfoReminderTour");
|
||||
this.tour = "";
|
||||
this.name = _name;
|
||||
this.active = false;
|
||||
var self = this;
|
||||
|
||||
this.init = function(callback) {
|
||||
//console.log("InfoReminderTour >> f:init()");
|
||||
|
||||
this.tour = function() {
|
||||
$('#help_InfoReminder').joyride({
|
||||
autoStart: false,
|
||||
modal: true,
|
||||
expose: true,
|
||||
'tipAdjustmentX': 15,
|
||||
'tipAdjustmentY': 15,
|
||||
'tipLocation': 'bottom', // 'top' or 'bottom' in relation to parent
|
||||
'nubPosition': 'auto', // override on a per tooltip bases
|
||||
'scrollSpeed': 300, // Page scrolling speed in ms
|
||||
'nextButton': true, // true/false for next button visibility
|
||||
'tipAnimation': 'fade', // 'pop' or 'fade' in each tip
|
||||
'tipAnimationFadeSpeed': 350, // if 'fade'- speed in ms of transition
|
||||
'preRideCallback' : self.preRideCallback,
|
||||
'postStepCallback': self.postStepCallback, // A method to call after each step
|
||||
'postRideCallback': self.postRideCallback // a method to call once the tour closes
|
||||
});
|
||||
}
|
||||
this.tour();
|
||||
if (callback != undefined) callback();
|
||||
};
|
||||
|
||||
this.preRideCallback = function(index, tip) {
|
||||
//console.log("InfoReminderTour >> f:preRideCallback() >> index: " + index + ", tip: " , tip);
|
||||
};
|
||||
this.postStepCallback = function(index, tip) {
|
||||
//console.log("InfoReminderTour >> f:postStepCallback() >> index: " + index + ", tip: " , tip);
|
||||
};
|
||||
this.postRideCallback = function(index, tip) {
|
||||
//console.log("InfoReminderTour >> f:postRideCallback() >> index: " + index + ", tip: " , tip);
|
||||
this.active = false;
|
||||
$(document).trigger(helpTours.TOURFINISHED, self.name);
|
||||
};
|
||||
|
||||
this.start = function() {
|
||||
//console.log("InfoReminderTour >> f:start()");
|
||||
this.active = true;
|
||||
$(window).joyride('restart');
|
||||
// self.tour();
|
||||
};
|
||||
}
|
||||
|
||||
function initHelp() {
|
||||
//console.log("f:initHelp()");
|
||||
|
||||
// track number of visits of this user
|
||||
if ($.cookie("Doodle3DVisitCounter") == null) {
|
||||
$.cookie("Doodle3DVisitCounter", '0');
|
||||
} else {
|
||||
$.cookie("Doodle3DVisitCounter", parseInt($.cookie("Doodle3DVisitCounter")) + 1);
|
||||
}
|
||||
|
||||
// load the html file which describes the tour contents
|
||||
$("#helpContainer").load("helpcontent.html", function() {
|
||||
//console.log("helpContent loaded");
|
||||
|
||||
helpTours = new HelpTours();
|
||||
|
||||
helpTours.init( function () {
|
||||
|
||||
|
||||
if (parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) {
|
||||
//console.log("initHelp >> Doodle3DFirstTime cookie is set, Doodle3DVisitCounter is < 4");
|
||||
if ($.cookie("Doodle3DFirstTime") != "ridden") {
|
||||
setTimeout(helpTours.startTour, 750, helpTours.tours.grandTour, helpTours);
|
||||
} else {
|
||||
setTimeout(helpTours.startTour, 750, helpTours.tours.infoReminderTour, helpTours);
|
||||
}
|
||||
// remind user of our nifty tour
|
||||
} else if (parseInt($.cookie("Doodle3DVisitCounter")) == helpTours.numTimesToShowNagPopup && $.cookie("Doodle3DFirstTime") != "ridden") {
|
||||
// remind
|
||||
setTimeout(helpTours.startTour, 750, helpTours.tours.infoReminderTour, helpTours);
|
||||
}
|
||||
// // only trigger starttour if user is seeing Doodle3D for the first time
|
||||
// if ($.cookie("Doodle3DFirstTime") != "ridden") {
|
||||
// console.log("initHelp >> intro tour has not been given yet > let's go!");
|
||||
// setTimeout(helpTours.startTour, 750, helpTours.tours.grandTour, helpTours);
|
||||
// } else if (parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) {
|
||||
// console.log("initHelp >> Doodle3DFirstTime cookie is set, Doodle3DVisitCounter is < 4");
|
||||
// // remind user of our nifty tour
|
||||
// setTimeout(helpTours.startTour, 750, helpTours.tours.infoReminderTour, helpTours);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var helpTours;
|
||||
function HelpTours() {
|
||||
//console.log("HelpTours");
|
||||
|
||||
this.numTimesToShowNagPopup = 2;
|
||||
|
||||
this.WELCOMETOUR = "welcometour";
|
||||
this.INFOREMINDER = "inforeminder";
|
||||
this.TOURFINISHED = "tourfinished";
|
||||
this.tours = {
|
||||
'grandTour' : this.WELCOMETOUR,
|
||||
'infoReminderTour' : this.INFOREMINDER
|
||||
};
|
||||
|
||||
this.currActiveTour = "";
|
||||
this.tourActive = false;
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function(callback) {
|
||||
//console.log("HelpTours >> f:init >> self: " + self);
|
||||
$(document).on(this.TOURFINISHED, this.tourEnded);
|
||||
|
||||
grandTour = new GrandTour(this.WELCOMETOUR);
|
||||
infoReminderTour = new InfoReminderTour(this.INFOREMINDER);
|
||||
|
||||
// this.tours["grandTour"] = self.WELCOMETOUR;
|
||||
// this.tours["infoReminderTour "]= self.INFOREMINDER;
|
||||
//console.log("HelpTours >> f:init >> this.tours: " , this.tours);
|
||||
|
||||
if (callback != undefined) callback();
|
||||
};
|
||||
|
||||
|
||||
this.startTour = function(which, scope) {
|
||||
if (scope == undefined) scope = this;
|
||||
// console.log("HelpTours >> f:startTour >> scope: " , scope);
|
||||
// console.log("HelpTours >> f:startTour >> currActiveTour: " , scope.currActiveTour.name);
|
||||
// console.log("HelpTours >> f:startTour >> currActiveTour.active: " , scope.currActiveTour.active);
|
||||
// console.log("HelpTours >> f:startTour >> target to start: '" + which);
|
||||
|
||||
|
||||
switch (which) {
|
||||
case scope.WELCOMETOUR:
|
||||
// do welcometour
|
||||
//console.log("HelpTours >> f:startTour >> case this.WELCOMETOUR >> scope.tourActive = " + scope.tourActive);
|
||||
//console.log("HelpTours >> f:startTour >> case this.WELCOMETOUR");
|
||||
if (scope.tourActive) {
|
||||
if (scope.currActiveTour.active == true) {
|
||||
$(window).joyride('end');
|
||||
scope.currActiveTour = undefined;
|
||||
}
|
||||
scope.tourActive = false;
|
||||
}
|
||||
$(window).joyride('destroy');
|
||||
// var self = this;
|
||||
grandTour.init();
|
||||
setTimeout(function(scp) {
|
||||
grandTour.start();
|
||||
scp.currActiveTour = grandTour;
|
||||
scp.tourActive = true;
|
||||
}, 250, scope);
|
||||
// $(window).joyride('restart');
|
||||
|
||||
break;
|
||||
case self.INFOREMINDER:
|
||||
// do info reminder
|
||||
// console.log("HelpTours >> f:startTour >> case self.INFOREMINDER >> scope.tourActive = " + scope.tourActive);
|
||||
//console.log("HelpTours >> f:startTour >> case self.INFOREMINDER");
|
||||
if (scope.tourActive) {
|
||||
// console.log(" killing previous joyride... ");
|
||||
if (scope.currActiveTour.active == true) {
|
||||
$(window).joyride('end');
|
||||
scope.currActiveTour = undefined;
|
||||
}
|
||||
// console.log(" setting tourActive to false....");
|
||||
scope.tourActive = false;
|
||||
// console.log(" scope.tourActive: " + scope.tourActive);
|
||||
}
|
||||
$(window).joyride('destroy');
|
||||
// var self = this;
|
||||
infoReminderTour.init();
|
||||
setTimeout(function(scp) {
|
||||
infoReminderTour.start();
|
||||
scp.currActiveTour = infoReminderTour;
|
||||
scp.tourActive = true;
|
||||
}, 250, scope);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.tourEnded = function(e, n) {
|
||||
//console.log("HelpTours >> f:tourEnded >> self.tourActive: " + self.tourActive + ", name: " + n);
|
||||
|
||||
$(window).joyride('destroy');
|
||||
self.currActiveTour = undefined;
|
||||
self.tourActive = false;
|
||||
|
||||
message.hide();
|
||||
printer.checkStatus();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
var keyboardShortcutsEnabled = true;
|
||||
var keyboardEscapeEnterEnabled = false;
|
||||
var wordBuffer = "";
|
||||
|
||||
var wordFuncs = {
|
||||
"idbeholdl": function() {
|
||||
alert("Light!");
|
||||
},
|
||||
"idspispopd": function() {
|
||||
drawTextOnCanvas("Im in ur kanvas drawin' ur stuffz.");
|
||||
},
|
||||
"dia": function() {
|
||||
var cx = canvasWidth / 2;
|
||||
var cy = canvasHeight /2;
|
||||
drawCircle(cx, cy, 50, 4);
|
||||
shapeMoveTo(cx - 20, cy);
|
||||
shapeLineTo(cx + 20, cy);
|
||||
shapeMoveTo(cx, cy - 20);
|
||||
shapeLineTo(cx, cy + 20);
|
||||
},
|
||||
"stats": function() {
|
||||
var text = "Shape statistics:\nNumber of points: " + _points.length;
|
||||
alert(text);
|
||||
},
|
||||
"pdump": function() {
|
||||
console.log("points array: " + _points);
|
||||
}
|
||||
};
|
||||
|
||||
function initKeyboard() {
|
||||
|
||||
$(document).keypress(function(event) {
|
||||
|
||||
if (keyboardEscapeEnterEnabled) {
|
||||
switch (event.keyCode) {
|
||||
case 13:
|
||||
$(document).trigger("onEnterKey");
|
||||
break;
|
||||
case 27:
|
||||
$(document).trigger("onEscapeKey");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!keyboardShortcutsEnabled) return;
|
||||
if (event.ctrlKey && event.altKey && ! event.metaKey) processWords(event);
|
||||
if (event.altKey || event.ctrlKey || event.metaKey) return; //ignore key presses with modifier keys except shift
|
||||
|
||||
var ch = String.fromCharCode(event.which);
|
||||
|
||||
switch (ch) {
|
||||
case 'c': newSketch(); break;
|
||||
case 'n': newSketch(); break;
|
||||
case 'p': print(); break;
|
||||
case 'u': oopsUndo(); break;
|
||||
case 'g': settingsWindow.downloadGcode(); break;
|
||||
case 'q': stopPrint(); break;
|
||||
case ',': openSettingsWindow(); break;
|
||||
case 'h': previewUp(true); break;
|
||||
case 'H': previewDown(true); break;
|
||||
case 's': saveSketch(); break;
|
||||
case 'L': nextSketch(); break;
|
||||
case 'l': prevSketch(); break;
|
||||
case '[': previewTwistLeft(); break;
|
||||
case ']': previewTwistRight(); break;
|
||||
case '|': resetTwist(); break;
|
||||
case 't': showWordArtDialog(); break;
|
||||
case 'i': showShapeDialog(); break;
|
||||
case 'T': showScanDialog(); break;
|
||||
|
||||
case ';': moveShape(-5,0); break;
|
||||
case '\'': moveShape(5,0); break;
|
||||
case '-': zoomShape(.95); break;
|
||||
case '+': zoomShape(1.05); break;
|
||||
case 'r': rotateShape(.1); break;
|
||||
case 'R': rotateShape(-.1); break;
|
||||
|
||||
//default: console.log("Key: '" + ch + "' (" + event.which + ")");
|
||||
}
|
||||
if(event.which != 13) { // don't prevent enter usage, it's used in tour
|
||||
event.preventDefault(); //prevents the character to end up in a focussed textfield
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function processWords(e) {
|
||||
wordBuffer += String.fromCharCode(e.which);
|
||||
|
||||
var match = false;
|
||||
for (var k in wordFuncs) {
|
||||
if (k.indexOf(wordBuffer) == 0) {
|
||||
if (k.length == wordBuffer.length) match = wordFuncs[k];
|
||||
else match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(match) == 'function') {
|
||||
match();
|
||||
wordBuffer = "";
|
||||
} else if (!match) {
|
||||
wordBuffer = "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function Message() {
|
||||
|
||||
Message.ERROR = "error";
|
||||
Message.WARNING = "warning";
|
||||
Message.NOTICE = "notice";
|
||||
Message.INFO = "info";
|
||||
|
||||
this.mode = "";
|
||||
|
||||
this.$element;
|
||||
|
||||
var self = this;
|
||||
var autoHideDelay = 5000;
|
||||
var autohideTimeout;
|
||||
|
||||
this.init = function($element) {
|
||||
this.$element = $element;
|
||||
}
|
||||
this.set = function(contents,mode,autoHide,disableEffect) {
|
||||
//console.log("Message:set: ",contents,mode,autoHide,disableEffect);
|
||||
if(disableEffect) {
|
||||
self.fill(contents,mode,autoHide)
|
||||
} else{
|
||||
self.hide(function() {
|
||||
self.show();
|
||||
self.fill(contents,mode,autoHide)
|
||||
});
|
||||
}
|
||||
}
|
||||
this.fill = function(contents,mode,autoHide) {
|
||||
//console.log("Message:fill: ",text,mode,autoHide);
|
||||
self.clear();
|
||||
self.$element.html(contents);
|
||||
self.$element.addClass(mode);
|
||||
self.mode = mode;
|
||||
clearTimeout(autohideTimeout);
|
||||
if(autoHide) {
|
||||
autohideTimeout = setTimeout(function(){ self.hide()},autoHideDelay);
|
||||
}
|
||||
}
|
||||
this.clear = function($element) {
|
||||
this.$element.html("");
|
||||
this.$element.removeClass(this.mode);
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
this.$element.fadeIn(200);
|
||||
}
|
||||
this.hide = function(complete) {
|
||||
this.$element.fadeOut(200,complete);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
function Popup(element, mask) {
|
||||
var autoCloseEnabled = true;
|
||||
var enterEnabled = true;
|
||||
var self = this;
|
||||
|
||||
this.open = function(complete, disableMaskClick) {
|
||||
mask.fadeIn(POPUP_SHOW_DURATION);
|
||||
element.fadeIn(POPUP_SHOW_DURATION, complete);
|
||||
|
||||
keyboardShortcutsEnabled = false;
|
||||
keyboardEscapeEnterEnabled = true;
|
||||
|
||||
document.body.removeEventListener('touchmove', prevent, false);
|
||||
mask.bind("onButtonClick", self.cancel);
|
||||
$(document).bind("onEscapeKey", self.cancel);
|
||||
if (enterEnabled) $(document).bind("onEnterKey", self.commit);
|
||||
}
|
||||
|
||||
this.close = function(complete) {
|
||||
mask.fadeOut(POPUP_SHOW_DURATION);
|
||||
element.fadeOut(POPUP_SHOW_DURATION, complete);
|
||||
|
||||
keyboardShortcutsEnabled = true;
|
||||
keyboardEscapeEnterEnabled = false;
|
||||
|
||||
document.body.addEventListener('touchmove', prevent, false);
|
||||
mask.unbind("onButtonClick", self.cancel);
|
||||
$(document).unbind("onEscapeKey", self.cancel);
|
||||
if (enterEnabled) $(document).unbind("onEnterKey", self.commit);
|
||||
}
|
||||
|
||||
this.setEnterEnabled = function(enabled) { enterEnabled = enabled; }
|
||||
|
||||
this.setAutoCloseEnabled = function(enabled) { autoCloseEnabled = enabled; }
|
||||
|
||||
this.cancel = function() {
|
||||
$(element).trigger('onPopupCancel');
|
||||
if (autoCloseEnabled) self.close();
|
||||
}
|
||||
|
||||
this.commit = function() {
|
||||
$(element).trigger('onPopupCommit');
|
||||
if (autoCloseEnabled) self.close();
|
||||
}
|
||||
}
|
562
js/Printer.js
|
@ -1,271 +1,457 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
/* not using this now
|
||||
var $printProgressContainer = $("#printProgressContainer");
|
||||
var $progressbar = $("#progressbar");
|
||||
var $progressAmount = $(".progressAmount");
|
||||
function setPrintprogress(val) {
|
||||
if (isNaN(val)) return;
|
||||
// console.log("f:setPrintprogress() >> val " + val);
|
||||
$progressbar.css("width", val*100 + "%");
|
||||
$progressAmount.text(Math.floor(val*100) + "%");
|
||||
if (isNaN(val)) return;
|
||||
// console.log("f:setPrintprogress() >> val " + val);
|
||||
$progressbar.css("width", val*100 + "%");
|
||||
$progressAmount.text(Math.floor(val*100) + "%");
|
||||
}
|
||||
//*/
|
||||
|
||||
function Printer() {
|
||||
|
||||
Printer.UNKNOWN_STATE = "unknown";
|
||||
Printer.DISCONNECTED_STATE = "disconnected";
|
||||
Printer.IDLE_STATE = "idle"; // printer found, but idle
|
||||
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
||||
Printer.PRINTING_STATE = "printing";
|
||||
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
||||
/* CONSTANTS */
|
||||
|
||||
this.temperature = 0;
|
||||
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
|
||||
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
|
||||
Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected
|
||||
Printer.CONNECTING_STATE = "connecting"; // printer connecting (printer found, but driver has not yet finished setting up the connection)
|
||||
Printer.IDLE_STATE = "idle"; // printer found and ready to use, but idle
|
||||
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
||||
Printer.PRINTING_STATE = "printing";
|
||||
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
||||
Printer.TOUR_STATE = "tour"; // when in joyride mode
|
||||
|
||||
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being sent to the printer, leaving will result in a incomplete 3D print";
|
||||
|
||||
//after buffer full message has been received, wait until the buffer load is below this ratio before sending new data
|
||||
Printer.GCODE_BUFFER_WAIT_LOAD_RATIO = 0.75;
|
||||
Printer.BUFFER_SPACE_WAIT_TIMEOUT = 30000; // how often to recheck buffer load
|
||||
|
||||
//time to wait when wifibox connection is lost while printing
|
||||
Printer.DISCONNECTED_RETRY_DELAY = 5000;
|
||||
|
||||
Printer.MAX_LINES_PER_POST = 500; // max amount of gcode lines per post (limited because WiFi box can't handle too much)
|
||||
Printer.MAX_GCODE_SIZE = 10; // max size of gcode in MB's (estimation)
|
||||
|
||||
// Events
|
||||
Printer.UPDATE = "update";
|
||||
|
||||
|
||||
/* MEMBER VARIABLES */
|
||||
|
||||
this.temperature = 0;
|
||||
this.targetTemperature = 0;
|
||||
this.currentLine = 0;
|
||||
this.totalLines = 0;
|
||||
this.bufferedLines = 0;
|
||||
this.state = Printer.UNKNOWN_STATE;
|
||||
this.hasControl = true; // whether this client has control access
|
||||
|
||||
this.wifiboxURL;
|
||||
|
||||
this.checkStatusInterval = 3000;
|
||||
this.checkStatusDelay;
|
||||
this.timeoutTime = 3000;
|
||||
this.sendPrintPartTimeoutTime = 5000;
|
||||
|
||||
this.gcode; // gcode to be printed
|
||||
this.sendLength = 1500; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
|
||||
this.currentLine = 0;
|
||||
this.totalLines = 0;
|
||||
this.bufferedLines = 0;
|
||||
this.bufferSize = 0;
|
||||
this.maxBufferSize = 0;
|
||||
this.state = Printer.UNKNOWN_STATE;
|
||||
this.hasControl = true; // whether this client has control access
|
||||
|
||||
this.retryDelay = 2000; // retry setTimout delay
|
||||
this.retrySendPrintPartDelay; // retry setTimout instance
|
||||
this.wifiboxURL;
|
||||
|
||||
this.checkStatusInterval = 3000;
|
||||
this.checkStatusDelay;
|
||||
this.timeoutTime = 3000;
|
||||
this.sendPrintPartTimeoutTime = 5000;
|
||||
|
||||
this.gcode = []; // gcode to be printed
|
||||
this.gcodeNumChunks = 0; //number of chunks to be sent (used for sequence numbering)
|
||||
|
||||
this.retryDelay = 2000; // retry setTimout delay
|
||||
this.retrySendPrintPartDelay; // retry setTimout instance
|
||||
this.retryCheckStatusDelay; // retry setTimout instance
|
||||
this.retryStopDelay; // retry setTimout instance
|
||||
this.retryPreheatDelay; // retry setTimout instance
|
||||
|
||||
this.maxGCodeSize = 10; // max size of gcode in MB's (estimation)
|
||||
|
||||
this.retryStopDelay; // retry setTimout instance
|
||||
this.retryPreheatDelay; // retry setTimout instance
|
||||
|
||||
this.stateOverruled = false;
|
||||
|
||||
|
||||
// Events
|
||||
Printer.UPDATE = "update";
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
var self = this;
|
||||
|
||||
|
||||
this.init = function() {
|
||||
console.log("Printer:init");
|
||||
//console.log("Printer:init");
|
||||
//this.wifiboxURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
||||
//this.wifiboxURL = "http://192.168.5.1/cgi-bin/d3dapi";
|
||||
this.wifiboxURL = wifiboxURL;
|
||||
//this.wifiboxURL = "proxy5.php";
|
||||
console.log(" wifiboxURL: ",this.wifiboxURL);
|
||||
|
||||
if(autoUpdate) {
|
||||
this.checkStatus();
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(" wifiboxURL: ",this.wifiboxURL);
|
||||
|
||||
if (autoUpdate) {
|
||||
this.startStatusCheckInterval();
|
||||
}
|
||||
}
|
||||
|
||||
this.preheat = function() {
|
||||
console.log("Printer:preheat");
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/heatup",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:preheat response: ",data);
|
||||
if(data.status == "error") {
|
||||
clearTimeout(self.retryPreheatDelay);
|
||||
console.log("Printer:preheat");
|
||||
|
||||
if (this.state != Printer.IDLE_STATE) return;
|
||||
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/heatup",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:preheat response: ",data);
|
||||
if(data.status != "success") {
|
||||
clearTimeout(self.retryPreheatDelay);
|
||||
self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
}).fail(function() {
|
||||
console.log("Printer:preheat: failed");
|
||||
clearTimeout(self.retryPreheatDelay);
|
||||
self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:preheat() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
console.log ("Printer >> f:preheat() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.print = function(gcode) {
|
||||
console.log("Printer:print");
|
||||
console.log(" gcode total # of lines: " + gcode.length);
|
||||
|
||||
/*for (i = 0; i < gcode.length; i++) {
|
||||
console.log("Printer:print");
|
||||
console.log(" gcode total # of lines: " + gcode.length);
|
||||
|
||||
message.set("Sending doodle to printer...",Message.NOTICE);
|
||||
self.addLeaveWarning();
|
||||
|
||||
/*for (i = 0; i < gcode.length; i++) {
|
||||
gcode[i] += " (" + i + ")";
|
||||
}*/
|
||||
|
||||
|
||||
this.sendIndex = 0;
|
||||
this.gcode = gcode;
|
||||
|
||||
//console.log(" gcode[20]: ",gcode[20]);
|
||||
var gcodeLineSize = this.byteSize(gcode[20]);
|
||||
//console.log(" gcodeLineSize: ",gcodeLineSize);
|
||||
var gcodeSize = gcodeLineSize*gcode.length/1024/1024; // estimate gcode size in MB's
|
||||
console.log(" gcodeSize: ",gcodeSize);
|
||||
|
||||
if(gcodeSize > this.maxGCodeSize) {
|
||||
console.log("Error: Printer:print: gcode file is probably to big ("+gcodeSize+"MB) (max: "+this.maxGCodeSize+"MB)");
|
||||
return;
|
||||
}
|
||||
|
||||
//this.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
|
||||
this.sendPrintPart(this.sendIndex, this.sendLength);
|
||||
this.gcode = gcode;
|
||||
this.gcodeNumChunks = Math.ceil(this.gcode.length / Printer.MAX_LINES_PER_POST);
|
||||
|
||||
//console.log(" gcode[20]: ",gcode[20]);
|
||||
var gcodeLineSize = this.byteSize(gcode[20]);
|
||||
//console.log(" gcodeLineSize: ",gcodeLineSize);
|
||||
var gcodeSize = gcodeLineSize*gcode.length/1024/1024; // estimate gcode size in MB's
|
||||
console.log(" gcodeSize: ",gcodeSize);
|
||||
|
||||
if(gcodeSize > Printer.MAX_GCODE_SIZE) {
|
||||
var msg = "Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)";
|
||||
alert(msg);
|
||||
console.log(msg);
|
||||
|
||||
this.overruleState(Printer.IDLE_STATE);
|
||||
this.startStatusCheckInterval();
|
||||
message.hide();
|
||||
self.removeLeaveWarning();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//this.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
|
||||
this.sendPrintPart(this.sendIndex, Printer.MAX_LINES_PER_POST);
|
||||
}
|
||||
|
||||
this.byteSize = function(s){
|
||||
return~-encodeURI(s).split(/%..|./).length;
|
||||
}
|
||||
|
||||
this.sendPrintPart = function(sendIndex,sendLength) {
|
||||
console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength);
|
||||
var self = this;
|
||||
// Abort if stopping
|
||||
// sendPrintPart can be called by delayed retry after request timeout for example
|
||||
if (self.state === Printer.STOPPING_STATE) return;
|
||||
|
||||
var completed = false;
|
||||
if (this.gcode.length < (sendIndex + sendLength)) {
|
||||
sendLength = this.gcode.length - sendIndex;
|
||||
completed = true;
|
||||
}
|
||||
|
||||
|
||||
/* prepare post data */
|
||||
|
||||
var gcodePart = this.gcode.slice(sendIndex, sendIndex + sendLength);
|
||||
var firstOne = (sendIndex == 0) ? true : false;
|
||||
var start = firstOne; // start printing right away
|
||||
var seqNum = Math.floor(sendIndex / Printer.MAX_LINES_PER_POST);
|
||||
var postData = {
|
||||
gcode: gcodePart.join("\n"), total_lines: this.gcode.length,
|
||||
clear: firstOne, start: start,
|
||||
seq_number: seqNum, seq_total: this.gcodeNumChunks
|
||||
};
|
||||
|
||||
|
||||
var firstOne = (sendIndex == 0)? true : false;
|
||||
var start = firstOne; // start printing right away
|
||||
|
||||
var completed = false;
|
||||
if (this.gcode.length < (sendIndex + sendLength)) {
|
||||
console.log(" sending less than max sendLength (and last)");
|
||||
sendLength = this.gcode.length - sendIndex;
|
||||
//lastOne = true;
|
||||
completed = true;
|
||||
}
|
||||
var gcodePart = this.gcode.slice(sendIndex, sendIndex+sendLength);
|
||||
|
||||
var postData = { gcode: gcodePart.join("\n"), first: firstOne, start: start};
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/print",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: this.sendPrintPartTimeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:sendPrintPart response: ",data);
|
||||
|
||||
if(data.status == "success") {
|
||||
if (completed) {
|
||||
console.log("Printer:sendPrintPart:gcode sending completed");
|
||||
this.gcode = [];
|
||||
btnStop.css("display","block");
|
||||
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
} else {
|
||||
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
|
||||
|
||||
console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")");
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
||||
console.log("Printer:sendPrintPart:sending next part");
|
||||
self.sendPrintPart(sendIndex + sendLength, sendLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* inform user what's going on */
|
||||
|
||||
var lessThanMaxText = completed ? " (last one, max=" + Printer.MAX_LINES_PER_POST + ")" : "";
|
||||
console.log("Printer:sendPrintPart: sendIndex=" + sendIndex + "/" + this.gcode.length +
|
||||
", sendLength=" + sendLength + lessThanMaxText +
|
||||
", sequence numbers: " + seqNum + "/" + this.gcodeNumChunks);
|
||||
|
||||
var sendPercentage = Math.round(sendIndex / this.gcode.length * 100);
|
||||
message.set("Sending doodle to printer: " + sendPercentage + "%", Message.NOTICE, false, true);
|
||||
|
||||
|
||||
/* send data */
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/print",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: this.sendPrintPartTimeoutTime,
|
||||
success: function(data){
|
||||
//console.log("Printer:sendPrintPart success response: ", data);
|
||||
|
||||
if(data.status == "success") {
|
||||
if (completed) {
|
||||
console.log("Printer:sendPrintPart: gcode sending completed");
|
||||
this.gcode = [];
|
||||
this.gcodeNumChunks = 0;
|
||||
self.removeLeaveWarning();
|
||||
message.set("Doodle has been sent to printer...",Message.INFO,true);
|
||||
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
} else {
|
||||
// only if the state hasn't been changed (by for example pressing stop) we send more gcode
|
||||
|
||||
//console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")");
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
||||
//console.log("Printer:sendPrintPart:sending next part");
|
||||
self.sendPrintPart(sendIndex + sendLength, sendLength);
|
||||
} else if (Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||
console.warn("Printer:sendPrintPart: wifibox connection lost while printing, retrying in " + (Printer.DISCONNECTED_RETRY_DELAY / 1000) + " seconds");
|
||||
clearTimeout(self.retrySendPrintPartDelay);
|
||||
self.retrySendPrintPartDelay = setTimeout(function() {
|
||||
console.log("Printer:sendPrintPart: retrying after wifibox disconnect was detected");
|
||||
self.sendPrintPart(sendIndex, sendLength);
|
||||
}, Printer.DISCONNECTED_RETRY_DELAY);
|
||||
}
|
||||
}
|
||||
} else if (data.status == "fail") {
|
||||
if (data.data.status == "buffer_full") {
|
||||
console.log("Printer:sendPrintPart: print server reported buffer full, pausing data transmission");
|
||||
//this will wait in a setTimeout loop until enough room is available and then call sendPrintPart again.
|
||||
self.waitForBufferSpace(sendIndex, sendLength);
|
||||
} else if (data.data.status == "seq_num_mismatch" && data.data.seq_number == seqNum) {
|
||||
console.warn("Printer:sendPrintPart: received sequence error, server is one chunk ahead. Proceeding with next chunk...");
|
||||
self.sendPrintPart(sendIndex + sendLength, sendLength);
|
||||
} else {
|
||||
console.error("Printer:sendPrintPart: unexpected failure response for API endpoint printer/print (" +
|
||||
data.data.status + ", current server seq. info: " + data.data.seq_number + "/" + data.data.seq_total + ")");
|
||||
//sequence errors should not occur, except perhaps when 'stop' was clicked while still sending (https://github.com/Doodle3D/doodle3d-client/issues/226).
|
||||
if (self.state != Printer.STOPPING_STATE) {
|
||||
message.set("Unexpected error sending doodle to printer (" + data.data.status + "), please retry", Message.ERROR, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// after we know the first gcode part has been received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
if(sendIndex == 0) {
|
||||
self.startStatusCheckInterval();
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:sendPrintPart: failed");
|
||||
}).fail(function(jqXHr, textStatus, errorThrown) {
|
||||
console.error("Printer:sendPrintPart: failed (AJAX status: '" + textStatus + "') AJAX exception (if any):", errorThrown);
|
||||
console.warn("Printer:sendPrintPart: retrying in " + (Printer.DISCONNECTED_RETRY_DELAY / 1000) + " seconds");
|
||||
clearTimeout(self.retrySendPrintPartDelay);
|
||||
self.retrySendPrintPartDelay = setTimeout(function() {
|
||||
console.log("request printer:sendPrintPart failed retry");
|
||||
self.sendPrintPart(sendIndex, sendLength)
|
||||
},self.retryDelay); // retry after delay
|
||||
console.log("Printer:sendPrintPart: retrying after AJAX failure");
|
||||
self.sendPrintPart(sendIndex, sendLength)
|
||||
}, Printer.DISCONNECTED_RETRY_DELAY);
|
||||
|
||||
// after we know the gcode packed has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by sendPrintPart when a buffer_full fail response is received.
|
||||
* This function keeps calling itself until the GCodeBuffer's load ratio
|
||||
* drops below a predefined value and then calls sendPrintPart again.
|
||||
*/
|
||||
this.waitForBufferSpace = function(sendIndex,sendLength) {
|
||||
var fillRatio = this.bufferSize / this.maxBufferSize;
|
||||
var self = this;
|
||||
|
||||
//console.log("buffer fill state: " + self.bufferSize + "/" + self.maxBufferSize + " (" + fillPercent + "%)");
|
||||
|
||||
if (fillRatio >= Printer.GCODE_BUFFER_WAIT_LOAD_RATIO) {
|
||||
var fillPercent = (fillRatio * 100).toFixed(2);
|
||||
console.log("Printer:waitForBufferSpace: waiting until gcode buffer load ratio is below " +
|
||||
(Printer.GCODE_BUFFER_WAIT_LOAD_RATIO * 100) + "% (current: " + fillPercent + "% of " +
|
||||
(self.maxBufferSize / 1024) + "KiB)");
|
||||
self.waitForBufferSpaceDelay = setTimeout(function() { self.waitForBufferSpace(sendIndex, sendLength); }, Printer.BUFFER_SPACE_WAIT_TIMEOUT);
|
||||
} else {
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
||||
console.log("Printer:waitForBufferSpace: load ratio dropped below " + (Printer.GCODE_BUFFER_WAIT_LOAD_RATIO * 100) + "%, calling sendPrintPart...");
|
||||
self.sendPrintPart(sendIndex, sendLength);
|
||||
} else {
|
||||
console.log("Printer:waitForBufferSpace: load ratio dropped far enough but printer state is not printing or buffering anymore, not resuming.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.stop = function() {
|
||||
console.log("Printer:stop");
|
||||
console.log("Printer:stop");
|
||||
var self = this;
|
||||
if (self.retrySendPrintPartDelay !== undefined) {
|
||||
clearTimeout(self.retrySendPrintPartDelay);
|
||||
}
|
||||
if (self.waitForBufferSpaceDelay !== undefined) {
|
||||
clearTimeout(self.waitForBufferSpaceDelay);
|
||||
}
|
||||
|
||||
endCode = generateEndCode();
|
||||
console.log(" endCode: ",endCode);
|
||||
var postData = { gcode: endCode.join("\n")};
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/stop",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:stop response: ", data);
|
||||
}
|
||||
}).fail(function() {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/stop",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:stop response: ", data);
|
||||
|
||||
// after we know the stop has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:stop: failed");
|
||||
clearTimeout(self.retryStopDelay);
|
||||
self.retryStopDelay = setTimeout(function() { self.stop() },self.retryDelay); // retry after delay
|
||||
|
||||
// after we know the stop has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:communicateWithWifibox() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
console.log ("Printer >> f:stop() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.startStatusCheckInterval = function() {
|
||||
console.log("Printer:startStatusCheckInterval");
|
||||
self.checkStatus();
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||
}
|
||||
|
||||
this.stopStatusCheckInterval = function() {
|
||||
console.log("Printer:stopStatusCheckInterval");
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
}
|
||||
|
||||
this.checkStatus = function() {
|
||||
console.log("Printer:checkStatus");
|
||||
//console.log("Printer:checkStatus");
|
||||
this.stateOverruled = false;
|
||||
console.log(" stateOverruled: ",this.stateOverruled);
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/info/status",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(response){
|
||||
console.log(" Printer:status: ",response.data.state); //," response: ",response);
|
||||
|
||||
self.handleStatusUpdate(response);
|
||||
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:checkStatus: failed");
|
||||
self.state = Printer.UNKNOWN_STATE;
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.retryCheckStatusDelay = setTimeout(function() { self.checkStatus() },self.retryDelay); // retry after delay
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/info/status",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(response){
|
||||
//console.log(" Printer:status: ",response.data.state); //," response: ",response);
|
||||
|
||||
self.handleStatusUpdate(response);
|
||||
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:checkStatus: failed");
|
||||
self.state = Printer.WIFIBOX_DISCONNECTED_STATE;
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.retryCheckStatusDelay = setTimeout(function() { self.checkStatus() },self.retryDelay); // retry after delay
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
this.handleStatusUpdate = function(response) {
|
||||
console.log("Printer:handleStatusUpdate");
|
||||
//console.log("Printer:handleStatusUpdate response: ",response);
|
||||
var data = response.data;
|
||||
if(response.status != "success") {
|
||||
self.state = Printer.UNKNOWN_STATE;
|
||||
} else {
|
||||
// state
|
||||
console.log(" stateOverruled: ",this.stateOverruled);
|
||||
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||
if(!this.stateOverruled) {
|
||||
self.state = data.state;
|
||||
console.log(" state > ",self.state);
|
||||
self.state = data.state;
|
||||
//console.log(" state > ",self.state);
|
||||
}
|
||||
|
||||
|
||||
// temperature
|
||||
self.temperature = data.hotend;
|
||||
self.targetTemperature = data.hotend_target;
|
||||
|
||||
self.temperature = data.hotend;
|
||||
self.targetTemperature = data.hotend_target;
|
||||
|
||||
// progress
|
||||
self.currentLine = data.current_line;
|
||||
self.totalLines = data.total_lines;
|
||||
self.bufferedLines = data.buffered_lines
|
||||
self.currentLine = data.current_line;
|
||||
self.totalLines = data.total_lines;
|
||||
self.bufferedLines = data.buffered_lines;
|
||||
self.bufferSize = data.buffer_size;
|
||||
self.maxBufferSize = data.max_buffer_size;
|
||||
|
||||
// access
|
||||
self.hasControl = data.has_control;
|
||||
|
||||
self.hasControl = data.has_control;
|
||||
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.STOPPING_STATE) {
|
||||
console.log("progress: ",self.currentLine+"/"+self.totalLines+" ("+self.bufferedLines+") ("+self.state+")");
|
||||
}
|
||||
}
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
}
|
||||
|
||||
this.overruleState = function(newState) {
|
||||
this.stateOverruled = true;
|
||||
console.log(" stateOverruled: ",this.stateOverruled);
|
||||
|
||||
|
||||
self.state = newState;
|
||||
|
||||
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
|
||||
this.stopStatusCheckInterval();
|
||||
}
|
||||
}
|
||||
|
||||
this.removeLeaveWarning = function() {
|
||||
window.onbeforeunload = null;
|
||||
}
|
||||
|
||||
this.addLeaveWarning = function() {
|
||||
window.onbeforeunload = function() {
|
||||
console.log("WARNING:"+Printer.ON_BEFORE_UNLOAD_MESSAGE);
|
||||
return Printer.ON_BEFORE_UNLOAD_MESSAGE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function Progressbar() {
|
||||
this.currProgress = 0; // default val
|
||||
|
||||
this.progressbarFGImg = new Image();
|
||||
this.progressbarFGImgSrc = "img/progress_fg.png";
|
||||
this.progressbarBGImg = new Image();
|
||||
this.progressbarBGImgSrc = "img/progress_bg.png";
|
||||
|
||||
this.progressWidth= 93;
|
||||
this.progressHeight = 82;
|
||||
|
||||
this.quartPI = .5 * Math.PI;
|
||||
this.twoPI = 2 * Math.PI;
|
||||
|
||||
// To make the progressbar start with a minimal amount of 'progress'
|
||||
// so that you can visually see that there is progress
|
||||
this.progressPadding = Math.PI * .1;
|
||||
|
||||
this.$canvas;
|
||||
this.canvas;
|
||||
this.context;
|
||||
this.$container;
|
||||
|
||||
this.isInitted = false;
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
this.init = function(targCanvas, targCanvasContainer) {
|
||||
console.log("Thermometer.init()");
|
||||
|
||||
this.$container = targCanvasContainer;
|
||||
|
||||
this.$canvas = targCanvas;
|
||||
this.canvas = this.$canvas[0];
|
||||
this.context = this.canvas.getContext('2d');
|
||||
|
||||
|
||||
var self = this;
|
||||
this.progressbarBGImg.onload = function() {
|
||||
//console.log("progressbarBGImg img loaded");
|
||||
// self.isInitted = true;
|
||||
// self.update(self.currentTemperature, self.targetTemperature);
|
||||
|
||||
self.progressbarFGImg.onload = function() {
|
||||
console.log("progressbarFGImg img loaded");
|
||||
self.isInitted = true;
|
||||
self.update(0, 100);
|
||||
};
|
||||
self.progressbarFGImg.src = self.progressbarFGImgSrc;
|
||||
};
|
||||
this.progressbarBGImg.src = this.progressbarBGImgSrc;
|
||||
}
|
||||
|
||||
this.update = function(part, total) {
|
||||
//console.log("Progressbar.update(" + part + "," + total + ")");
|
||||
|
||||
var pct = part / total;
|
||||
if (this.isInitted) {
|
||||
if (part == undefined) part = 0;
|
||||
if (total== undefined) total = 100; // prevent divide by zero
|
||||
|
||||
var progress = part / total;
|
||||
progress = Math.min(progress, 1.0);
|
||||
progress = Math.max(progress, 0);
|
||||
//console.log("progressbar >> f:update() >> progress: " + progress);
|
||||
|
||||
// clear
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
this.context.drawImage(this.progressbarBGImg, 0, 0);
|
||||
|
||||
this.context.font = "7pt sans-serif";
|
||||
|
||||
// draw the progressbar foreground's clipping path
|
||||
this.context.save();
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(45, 45);
|
||||
this.context.lineTo(45, 0);
|
||||
this.context.arc(45, 45, 45, -this.quartPI, -this.quartPI + this.progressPadding + (progress * (this.twoPI - this.progressPadding)), false); // circle bottom of thermometer
|
||||
this.context.lineTo(45, 45);
|
||||
this.context.clip();
|
||||
|
||||
this.context.drawImage(this.progressbarFGImg, 0, 0);
|
||||
this.context.restore();
|
||||
|
||||
if (debugMode) {
|
||||
this.context.fillStyle = '#222';
|
||||
this.context.strokeStyle = '#fff';
|
||||
this.context.lineWidth = 3;
|
||||
this.context.textAlign="center";
|
||||
this.context.strokeText(part + " / " + total, 45, 45, 90);
|
||||
this.context.fillText(part + " / " + total, 45, 45, 90);
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log("Progressbar.setTemperature() -> thermometer not initialized!");
|
||||
}
|
||||
}
|
||||
this.show = function() {
|
||||
this.$container.addClass("progressbarAppear");
|
||||
// this.$container.show();
|
||||
this.enabled = true;
|
||||
}
|
||||
this.hide = function() {
|
||||
this.$container.removeClass("progressbarAppear");
|
||||
// this.$container.hide();
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
|
@ -1,623 +0,0 @@
|
|||
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
|
||||
var settings = {
|
||||
"network.ap.ssid": "d3d-ap-%%MAC_ADDR_TAIL%%",
|
||||
"network.ap.address": "192.168.10.1",
|
||||
"network.ap.netmask": "255.255.255.0",
|
||||
"printer.temperature": 220,
|
||||
"printer.maxObjectHeight": 150,
|
||||
"printer.layerHeight": 0.2,
|
||||
"printer.wallThickness": 0.7,
|
||||
"printer.screenToMillimeterScale": 0.3,
|
||||
"printer.speed": 50,
|
||||
"printer.travelSpeed": 200,
|
||||
"printer.filamentThickness": 2.85,
|
||||
"printer.enableTraveling": true,
|
||||
"printer.useSubLayers": true,
|
||||
"printer.firstLayerSlow": true,
|
||||
"printer.autoWarmUp": true,
|
||||
"printer.simplify.iterations": 10,
|
||||
"printer.simplify.minNumPoints": 15,
|
||||
"printer.simplify.minDistance": 3,
|
||||
"printer.retraction.enabled": true,
|
||||
"printer.retraction.speed": 50,
|
||||
"printer.retraction.minDistance": 1,
|
||||
"printer.retraction.amount": 5,
|
||||
"printer.autoWarmUpCommand": "M104 S220 (hardcoded temperature)"
|
||||
}
|
||||
|
||||
|
||||
function SettingsWindow() {
|
||||
this.wifiboxURL;
|
||||
this.window;
|
||||
this.form;
|
||||
this.timeoutTime = 3000;
|
||||
this.retryDelay = 2000; // retry setTimout delay
|
||||
this.retryRetrieveNetworkStatusDelayTime = 1000;// retry setTimout delay
|
||||
|
||||
this.retryLoadSettingsDelay; // retry setTimout instance
|
||||
this.retrySaveSettingsDelay; // retry setTimout instance
|
||||
this.retryRetrieveNetworkStatusDelay;// retry setTimout instance
|
||||
|
||||
|
||||
this.apFieldSet;
|
||||
this.clientFieldSet;
|
||||
this.networks;
|
||||
this.currentNetwork; // the ssid of the network the box is on
|
||||
this.selectedNetwork; // the ssid of the selected network in the client mode settings
|
||||
this.currentLocalIP = "";
|
||||
this.clientModeState = SettingsWindow.NOT_CONNECTED;
|
||||
this.currentAP;
|
||||
this.apModeState = SettingsWindow.NO_AP;
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
this.retrieveNetworkStatusDelay; // setTimout delay
|
||||
this.retrieveNetworkStatusDelayTime = 1000;
|
||||
|
||||
// Events
|
||||
SettingsWindow.SETTINGS_LOADED = "settingsLoaded";
|
||||
|
||||
// network client mode states
|
||||
SettingsWindow.NOT_CONNECTED = "not connected"; // also used as first item in networks list
|
||||
SettingsWindow.CONNECTED = "connected";
|
||||
SettingsWindow.CONNECTING = "connecting";
|
||||
SettingsWindow.CONNECTING_FAILED = "connecting failed"
|
||||
|
||||
// network access point mode states
|
||||
SettingsWindow.NO_AP = "no ap";
|
||||
SettingsWindow.AP = "ap";
|
||||
SettingsWindow.CREATING_AP = "creating ap";
|
||||
|
||||
|
||||
SettingsWindow.API_CONNECTING_FAILED = -1
|
||||
SettingsWindow.API_NOT_CONNECTED = 0
|
||||
SettingsWindow.API_CONNECTING = 1
|
||||
SettingsWindow.API_CONNECTED = 2
|
||||
SettingsWindow.API_CREATING = 3
|
||||
SettingsWindow.API_CREATED = 4
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function(wifiboxURL) {
|
||||
this.wifiboxURL = wifiboxURL;
|
||||
|
||||
this.window = $("#settings");
|
||||
this.window.find(".btnOK").click(this.submitwindow);
|
||||
this.window.find(".settingsContainer").load("settings.html", function() {
|
||||
console.log("Settings:finished loading settings.html, now loading settings...");
|
||||
|
||||
self.form = self.window.find("form");
|
||||
self.form.submit(function (e) { self.submitwindow(e) });
|
||||
|
||||
self.loadSettings();
|
||||
|
||||
var btnAP = self.form.find("label[for='ap']");
|
||||
var btnClient = self.form.find("label[for='client']");
|
||||
var btnRefresh = self.form.find("#refreshNetworks");
|
||||
var btnConnect = self.form.find("#connectToNetwork");
|
||||
var btnCreate = self.form.find("#createAP");
|
||||
var networkSelector = self.form.find("#network");
|
||||
self.apFieldSet = self.form.find("#apSettings");
|
||||
self.clientFieldSet = self.form.find("#clientSettings");
|
||||
|
||||
btnAP.on('touchstart mousedown',self.showAPSettings);
|
||||
btnClient.on('touchstart mousedown',self.showClientSettings);
|
||||
btnRefresh.on('touchstart mousedown',self.refreshNetworks);
|
||||
btnConnect.on('touchstart mousedown',self.connectToNetwork);
|
||||
btnCreate.on('touchstart mousedown',self.createAP);
|
||||
networkSelector.change(self.networkSelectorChanged);
|
||||
});
|
||||
}
|
||||
this.submitwindow = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
self.saveSettings();
|
||||
self.hideSettings();
|
||||
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
}
|
||||
|
||||
this.showSettings = function() {
|
||||
console.log("f:showSettings()");
|
||||
|
||||
this.loadSettings(); // reload settings
|
||||
// this.window.css("display","table");
|
||||
$("#contentOverlay").fadeIn(375, function() {
|
||||
document.body.removeEventListener('touchmove',prevent,false);
|
||||
});
|
||||
}
|
||||
this.hideSettings = function() {
|
||||
$("#contentOverlay").fadeOut(375, function() {
|
||||
document.body.addEventListener('touchmove',prevent,false);
|
||||
// self.window.css("display","none");
|
||||
});
|
||||
}
|
||||
|
||||
this.loadSettings = function() {
|
||||
if (!communicateWithWifibox) {
|
||||
console.log(" communicateWithWifibox is false: settings aren't being loaded from wifibox...")
|
||||
return;
|
||||
}
|
||||
console.log("Settings:loadSettings() >> getting new data...");
|
||||
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/config/all",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Settings:loadSettings response: ",data);
|
||||
settings = data.data;
|
||||
console.log(" settings: ",settings);
|
||||
self.fillForm();
|
||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:loadSettings: failed");
|
||||
clearTimeout(self.retryLoadSettingsDelay);
|
||||
self.retryLoadSettingsDelay = setTimeout(function() { self.loadSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
|
||||
this.refreshNetworks();
|
||||
this.retrieveNetworkStatus(false);
|
||||
}
|
||||
|
||||
this.saveSettings = function(callback) {
|
||||
console.log("Settings:saveSettings");
|
||||
|
||||
this.readForm();
|
||||
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/config",
|
||||
type: "POST",
|
||||
data: settings,
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Settings:saveSettings response: ",data);
|
||||
if(data.status == "error") {
|
||||
clearTimeout(self.retrySaveSettingsDelay);
|
||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
} else {
|
||||
var savedSettings = data.data;
|
||||
$.each(savedSettings, function(index, val) {
|
||||
if (val != "ok") {
|
||||
console.log("ERROR: value '" + index + "' not successfully set. Message: " + val);
|
||||
}
|
||||
});
|
||||
// TODO something like a callback or feedback that saving went well / or failed
|
||||
if (callback != undefined) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:saveSettings: failed");
|
||||
clearTimeout(self.retrySaveSettingsDelay);
|
||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.fillForm = function() {
|
||||
console.log("SettingsWindow:fillForm");
|
||||
|
||||
//fill form with loaded settings
|
||||
var selects = this.form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var element = $(element);
|
||||
element.val(settings[element.attr('name')]);
|
||||
});
|
||||
var inputs = this.form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var element = $(element);
|
||||
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
|
||||
switch(element.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
element.val(settings[element.attr('name')]);
|
||||
break;
|
||||
case "checkbox":
|
||||
element.prop('checked', settings[element.attr('name')]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
var textareas = this.form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var element = $(element);
|
||||
var value = settings[element.attr('name')];
|
||||
element.val(value);
|
||||
});
|
||||
}
|
||||
|
||||
this.readForm = function() {
|
||||
console.log("SettingsWindow:readForm");
|
||||
var selects = this.form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var element = $(element);
|
||||
settings[element.attr('name')] = element.val();
|
||||
});
|
||||
|
||||
var inputs = this.form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var element = $(element);
|
||||
switch(element.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
settings[element.attr('name')] = element.val();
|
||||
break;
|
||||
case "checkbox":
|
||||
settings[element.attr('name')] = element.prop('checked')
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
var textareas = this.form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var element = $(element);
|
||||
settings[element.attr('name')] = element.val();
|
||||
});
|
||||
console.log(settings);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Networks ui
|
||||
*/
|
||||
this.showAPSettings = function() {
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.hide();
|
||||
}
|
||||
this.showClientSettings = function() {
|
||||
self.clientFieldSet.show();
|
||||
self.apFieldSet.hide();
|
||||
}
|
||||
this.refreshNetworks = function() {
|
||||
console.log("Settings:refreshNetworks");
|
||||
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/scan",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:refreshNetworks response: ",response);
|
||||
if(response.status == "error") {
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
} else {
|
||||
var networks = response.data.networks
|
||||
self.networks = {};
|
||||
var foundCurrentNetwork = false;
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.empty();
|
||||
networkSelector.append(
|
||||
$("<option></option>").val(SettingsWindow.NOT_CONNECTED).html("not connected")
|
||||
);
|
||||
$.each(networks, function(index,element) {
|
||||
if(element.ssid == self.currentNetwork) {
|
||||
foundCurrentNetwork = true;
|
||||
}
|
||||
networkSelector.append(
|
||||
$("<option></option>").val(element.ssid).html(element.ssid)
|
||||
);
|
||||
self.networks[element.ssid] = element;
|
||||
});
|
||||
if(foundCurrentNetwork) {
|
||||
networkSelector.val(self.currentNetwork);
|
||||
self.selectNetwork(self.currentNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.retrieveNetworkStatus = function(connecting) {
|
||||
//console.log("Settings:retrieveNetworkStatus");
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/status",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:retrieveNetworkStatus response: ",response);
|
||||
if(response.status == "error") {
|
||||
|
||||
} else {
|
||||
var data = response.data;
|
||||
|
||||
if(typeof data.status === 'string') {
|
||||
data.status = parseInt(data.status);
|
||||
}
|
||||
//console.log(" data.status: ",data.status,data.statusMessage);
|
||||
|
||||
// Determine which network settings to show
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_NOT_CONNECTED:
|
||||
//console.log(" not connected & not a access point");
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.show();
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTING_FAILED:
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
case SettingsWindow.API_CONNECTED:
|
||||
//console.log(" client mode");
|
||||
self.form.find("#client").prop('checked',true);
|
||||
|
||||
self.apFieldSet.hide();
|
||||
self.clientFieldSet.show();
|
||||
|
||||
if(data.status == SettingsWindow.API_CONNECTED) {
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.val(data.ssid);
|
||||
|
||||
self.currentNetwork = data.ssid;
|
||||
self.currentLocalIP = data.localip;
|
||||
self.selectNetwork(data.ssid);
|
||||
} else {
|
||||
self.currentLocalIP = ""
|
||||
}
|
||||
|
||||
break;
|
||||
case SettingsWindow.API_CREATING:
|
||||
case SettingsWindow.API_CREATED:
|
||||
//console.log(" access point mode");
|
||||
self.form.find("#ap").prop('checked',true);
|
||||
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.hide();
|
||||
|
||||
self.currentNetwork = undefined;
|
||||
self.selectNetwork(SettingsWindow.NOT_CONNECTED);
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.val(SettingsWindow.NOT_CONNECTED);
|
||||
|
||||
if(data.ssid) {
|
||||
self.currentAP = data.ssid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// update status message
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_CONNECTING_FAILED:
|
||||
self.setClientModeState(SettingsWindow.CONNECTING_FAILED,data.statusMessage);
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_NOT_CONNECTED:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTED:
|
||||
self.setClientModeState(SettingsWindow.CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CREATING:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CREATED:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.AP,"");
|
||||
break;
|
||||
}
|
||||
|
||||
// Keep checking for updates?
|
||||
if(connecting) {
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
case SettingsWindow.API_CREATING:
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
self.retryRetrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(connecting) },self.retryRetrieveNetworkStatusDelayTime); // retry after delay
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:retrieveNetworkStatus: failed");
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
self.retryRetrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(connecting) },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.networkSelectorChanged = function(e) {
|
||||
var selectedOption = $(this).find("option:selected");
|
||||
self.selectNetwork(selectedOption.val());
|
||||
}
|
||||
|
||||
this.selectNetwork = function(ssid) {
|
||||
console.log("select network: ",ssid);
|
||||
this.selectedNetwork = ssid;
|
||||
if(this.networks == undefined || ssid == SettingsWindow.NOT_CONNECTED) {
|
||||
this.hideWiFiPassword();
|
||||
} else {
|
||||
var network = this.networks[ssid];
|
||||
if(network.encryption == "none") {
|
||||
this.hideWiFiPassword();
|
||||
} else {
|
||||
this.showWiFiPassword();
|
||||
}
|
||||
this.form.find("#password").val("");
|
||||
}
|
||||
}
|
||||
this.showWiFiPassword = function() {
|
||||
this.form.find("#passwordLabel").show();
|
||||
this.form.find("#password").show();
|
||||
}
|
||||
this.hideWiFiPassword = function() {
|
||||
this.form.find("#passwordLabel").hide();
|
||||
this.form.find("#password").hide();
|
||||
}
|
||||
|
||||
this.setClientModeState = function(state,msg) {
|
||||
var field = this.form.find("#clientModeState");
|
||||
var btnConnect = self.form.find("#connectToNetwork");
|
||||
switch(state) {
|
||||
case SettingsWindow.NOT_CONNECTED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
field.html("Not connected");
|
||||
break;
|
||||
case SettingsWindow.CONNECTED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
|
||||
var fieldText = "Connected to: "+this.currentNetwork+".";
|
||||
if(this.currentLocalIP != undefined && this.currentLocalIP != "") {
|
||||
var a = "<a href='http://"+this.currentLocalIP+"' target='_black'>"+this.currentLocalIP+"</a>";
|
||||
fieldText += " Local ip: "+a;
|
||||
}
|
||||
field.html(fieldText);
|
||||
break;
|
||||
case SettingsWindow.CONNECTING:
|
||||
btnConnect.attr("disabled", true);
|
||||
field.html("Connecting...");
|
||||
break;
|
||||
case SettingsWindow.CONNECTING_FAILED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
field.html(msg);
|
||||
break;
|
||||
}
|
||||
this.clientModeState = state;
|
||||
}
|
||||
this.setAPModeState = function(state,msg) {
|
||||
var field = this.form.find("#apModeState");
|
||||
var btnCreate = this.form.find("#createAP");
|
||||
switch(state) {
|
||||
case SettingsWindow.NO_AP:
|
||||
btnCreate.removeAttr("disabled");
|
||||
field.html("Not currently a access point");
|
||||
break;
|
||||
case SettingsWindow.AP:
|
||||
btnCreate.removeAttr("disabled");
|
||||
field.html("Is access point: "+this.currentAP);
|
||||
break;
|
||||
case SettingsWindow.CREATING_AP:
|
||||
btnCreate.attr("disabled", true);
|
||||
field.html("Creating access point...");
|
||||
break;
|
||||
}
|
||||
this.apModeState = state;
|
||||
}
|
||||
|
||||
this.connectToNetwork = function() {
|
||||
console.log("connectToNetwork");
|
||||
if(self.selectedNetwork == undefined) return;
|
||||
postData = {
|
||||
ssid:self.selectedNetwork,
|
||||
phrase:self.form.find("#password").val(),
|
||||
recreate:true
|
||||
}
|
||||
console.log(" postData: ",postData);
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/associate",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:connectToNetwork response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:connectToNetwork: timeout (normal behavior)");
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
clearTimeout(self.retrieveNetworkStatusDelay);
|
||||
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
||||
}
|
||||
|
||||
this.createAP = function() {
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/openap",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:createAP response: ",response);
|
||||
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:createAP: timeout (normal behavior)");
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
clearTimeout(self.retrieveNetworkStatusDelay);
|
||||
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
*
|
||||
*
|
||||
* FROM DOODLE3D.INI
|
||||
*
|
||||
*/
|
||||
//TODO: find all references to these variables, replace them and finally remove these.
|
||||
var objectHeight = 20;
|
||||
var layerHeight = .2;
|
||||
//var wallThickness = .5;
|
||||
//var hop = 0;
|
||||
//var speed = 70;
|
||||
//var travelSpeed = 200;
|
||||
var enableTraveling = true;
|
||||
//var filamentThickness = 2.89;
|
||||
var minScale = .3;
|
||||
var maxScale = 1;
|
||||
var shape = "%";
|
||||
var twists = 0;
|
||||
//var useSubLayers = true;
|
||||
//var debug = false; // debug moved to main.js
|
||||
var loglevel = 2;
|
||||
//var zOffset = 0;
|
||||
var serverport = 8888;
|
||||
var autoLoadImage = "hand.txt";
|
||||
var loadOffset = [0, 0]; // x en y ?
|
||||
var showWarmUp = true;
|
||||
var loopAlways = false;
|
||||
var firstLayerSlow = true;
|
||||
var useSubpathColors = false;
|
||||
var autoWarmUp = true;
|
||||
//var maxObjectHeight = 150;
|
||||
var maxScaleDifference = .1;
|
||||
var frameRate = 60;
|
||||
var quitOnEscape = true;
|
||||
var screenToMillimeterScale = .3; // 0.3
|
||||
//var targetTemperature = 220;
|
||||
//var simplifyiterations = 10;
|
||||
//var simplifyminNumPoints = 15;
|
||||
//var simplifyminDistance = 3;
|
||||
//var retractionspeed = 50;
|
||||
//var retractionminDistance = 5;
|
||||
//var retractionamount = 3;
|
||||
var sideis3D = true;
|
||||
var sidevisible = true;
|
||||
var sidebounds = [900, 210, 131, 390];
|
||||
var sideborder = [880, 169, 2, 471];
|
||||
var windowbounds = [0, 0, 800, 500];
|
||||
var windowcenter = true;
|
||||
var windowfullscreen = false;
|
||||
var autoWarmUpCommand = "M104 S230";
|
||||
//var checkTemperatureInterval = 3;
|
||||
var autoWarmUpDelay = 3;
|
|
@ -0,0 +1,183 @@
|
|||
function drawCircle(x0,y0,r,res) {
|
||||
if (res==undefined) res = 50; //circle resolution
|
||||
beginShape();
|
||||
var step = Math.PI * 2.0 / res;
|
||||
for (var a=0; a<Math.PI*2; a+=step) {
|
||||
var x = Math.sin(a+Math.PI) * r + x0;
|
||||
var y = Math.cos(a+Math.PI) * r + y0;
|
||||
if (a==0) shapeMoveTo(x,y);
|
||||
else shapeLineTo(x,y);
|
||||
}
|
||||
|
||||
//close shape
|
||||
var x = Math.sin(0+Math.PI) * r + x0;
|
||||
var y = Math.cos(0+Math.PI) * r + y0;
|
||||
shapeLineTo(x,y);
|
||||
|
||||
endShape();
|
||||
}
|
||||
|
||||
function beginShape(x,y) {
|
||||
setSketchModified(true);
|
||||
}
|
||||
|
||||
function shapeMoveTo(x,y) {
|
||||
_points.push([x, y, true]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y, -1);
|
||||
}
|
||||
|
||||
function shapeLineTo(x,y) {
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
}
|
||||
|
||||
function endShape() {
|
||||
renderToImageDataPreview();
|
||||
}
|
||||
|
||||
function getBounds(points) {
|
||||
var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity;
|
||||
for (var i=0; i<points.length; i++) {
|
||||
var p = points[i];
|
||||
xMin = Math.min(xMin,p[0]);
|
||||
xMax = Math.max(xMax,p[0]);
|
||||
yMin = Math.min(yMin,p[1]);
|
||||
yMax = Math.max(yMax,p[1]);
|
||||
}
|
||||
return {x:xMin,y:yMin,width:xMax-xMin,height:yMax-yMin};
|
||||
}
|
||||
|
||||
function translatePoints(points,x,y) {
|
||||
for (var i=0; i<points.length; i++) {
|
||||
points[i][0] += x;
|
||||
points[i][1] += y;
|
||||
}
|
||||
}
|
||||
|
||||
function scalePoints(points,x,y) {
|
||||
if (y==undefined) y = x;
|
||||
for (var i=0; i<points.length; i++) {
|
||||
points[i][0] *= x;
|
||||
points[i][1] *= y;
|
||||
}
|
||||
}
|
||||
|
||||
function rotatePoints(points, radians, cx, cy) {
|
||||
if (cx==undefined) cx = 0;
|
||||
if (cy==undefined) cy = 0;
|
||||
|
||||
var cos = Math.cos(radians);
|
||||
var sin = Math.sin(radians);
|
||||
|
||||
for (var i=0; i<points.length; i++) {
|
||||
var x = points[i][0];
|
||||
var y = points[i][1];
|
||||
var nx = (cos * (x - cx)) - (sin * (y - cy)) + cx;
|
||||
var ny = (sin * (x - cx)) + (cos * (y - cy)) + cy;
|
||||
points[i][0] = nx;
|
||||
points[i][1] = ny;
|
||||
}
|
||||
}
|
||||
|
||||
function moveShape(x,y) {
|
||||
var bounds = getBounds(_points);
|
||||
var delta = reduceTransformToFit(x, y, 1.0, bounds);
|
||||
|
||||
if (delta.x != 0 || delta.y != 0) {
|
||||
translatePoints(_points, delta.x, delta.y);
|
||||
updateView();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: reduction of zoomValue is still not completely correct (but acceptable?)
|
||||
//TODO: bounds should be cached and marked dirty on modification of points array; translations could be combined in several places
|
||||
function zoomShape(zoomValue) {
|
||||
var bounds = getBounds(_points);
|
||||
var transform = reduceTransformToFit(0, 0, zoomValue, bounds);
|
||||
|
||||
translatePoints(_points, transform.x, transform.y); //move points towards center as far as necessary to avoid clipping
|
||||
translatePoints(_points, -bounds.x, -bounds.y);
|
||||
translatePoints(_points, -bounds.width / 2, -bounds.height / 2);
|
||||
scalePoints(_points, transform.zf, transform.zf);
|
||||
translatePoints(_points, bounds.width / 2, bounds.height / 2);
|
||||
translatePoints(_points, bounds.x, bounds.y);
|
||||
updateView();
|
||||
}
|
||||
|
||||
function rotateShape(radians) {
|
||||
var bounds = getBounds(_points);
|
||||
var cx = bounds.x + bounds.width/2;
|
||||
var cy = bounds.y + bounds.height/2;
|
||||
rotatePoints(_points, radians, cx, cy);
|
||||
|
||||
var bounds = getBounds(_points);
|
||||
var transform = reduceTransformToFit(0, 0, 1.0, bounds);
|
||||
translatePoints(_points, transform.x, transform.y);
|
||||
scalePoints(_points, transform.zf, transform.zf);
|
||||
|
||||
updateView();
|
||||
}
|
||||
|
||||
function updateView() {
|
||||
setSketchModified(true);
|
||||
redrawDoodle(true);
|
||||
adjustPreviewTransformation();
|
||||
renderToImageDataPreview();
|
||||
|
||||
if (debugMode) {
|
||||
var bounds = getBounds(_points);
|
||||
drawCircleTemp(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, 5, 'red');
|
||||
}
|
||||
}
|
||||
|
||||
//when x,y!=0,0: reduces them such that transformed bounds will still fit on canvas (given that they fit prior to the transform)
|
||||
//otherwise: calculate translation + zoom reduce such that given bounds will fit on canvas after transformation
|
||||
function reduceTransformToFit(x, y, zf, bounds) {
|
||||
var zw = bounds.width * zf; zh = bounds.height * zf;
|
||||
var newBounds = { x: bounds.x - (zw - bounds.width) / 2, y: bounds.y - (zh - bounds.height) / 2, width: zw, height: zh };
|
||||
// console.log("bounds: " + bounds.x + ", " + bounds.y + ", " + bounds.width + ", " + bounds.height);
|
||||
// console.log("newBounds: " + newBounds.x + ", " + newBounds.y + ", " + newBounds.width + ", " + newBounds.height);
|
||||
|
||||
var ldx = Math.max(x, -newBounds.x);
|
||||
var rdx = Math.min(x, canvasWidth - (newBounds.x + newBounds.width));
|
||||
var tdy = Math.max(y, -newBounds.y);
|
||||
var bdy = Math.min(y, canvasHeight - (newBounds.y + newBounds.height));
|
||||
|
||||
if (x != 0 || y != 0) { //movement was requested
|
||||
return { x: nearestZero(ldx, rdx), y: nearestZero(tdy, bdy) };
|
||||
} else { //no movement requested
|
||||
var delta = { x: ldx + rdx, y: tdy + bdy };
|
||||
if (ldx != 0 && rdx != 0) delta.x /= 2;
|
||||
if (tdy != 0 && bdy != 0) delta.y /= 2;
|
||||
|
||||
delta.x /= zf;
|
||||
delta.y /= zf;
|
||||
|
||||
var zxMax = Math.min(zf, canvasWidth / newBounds.width);
|
||||
var zyMax = Math.min(zf, canvasHeight / newBounds.height);
|
||||
// var oldZF = zf;
|
||||
// var dir = zf >= 1.0 ? 1 : 0;
|
||||
zf = Math.min(zxMax, zyMax);
|
||||
// if (dir == 1 && zf < 1.0) zf = 1;
|
||||
// console.log("orgZF, zxMax, zyMax, finZF: " + oldZF + ", " + zxMax + ", " + zyMax + ", " + zf);
|
||||
|
||||
return { x: delta.x, y: delta.y, zf: zf };
|
||||
}
|
||||
}
|
||||
|
||||
function nearestZero(v1, v2) { return Math.abs(v1) < Math.abs(v2) ? v1 : v2; }
|
||||
|
||||
//*draws* a circle (i.e. it is not added as points to shape)
|
||||
function drawCircleTemp(x, y, r, color) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.fillStyle = color;
|
||||
ctx.arc(x, y, r, 0, 2 * Math.PI, false);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.fillStyle = 'black';
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
//SVG validator: http://validator.w3.org/
|
||||
//SVG viewer: http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html
|
||||
function saveToSvg() {
|
||||
var lastX = 0, lastY = 0, lastIsMove = false;
|
||||
var svg = '';
|
||||
|
||||
var boundsWidth = doodleBounds[2] - doodleBounds[0];
|
||||
var boundsHeight = doodleBounds[3] - doodleBounds[1];
|
||||
|
||||
svg += '<?xml version="1.0" standalone="no"?>\n';
|
||||
svg += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
|
||||
svg += '<svg width="' + boundsWidth + '" height="' + boundsHeight + '" version="1.1" xmlns="http://www.w3.org/2000/svg">\n';
|
||||
svg += '\t<desc>Doodle 3D sketch</desc>\n';
|
||||
|
||||
var data = '';
|
||||
for (var i = 0; i < _points.length; ++i) {
|
||||
var x = _points[i][0], y = _points[i][1], isMove = _points[i][2];
|
||||
var dx = x - lastX, dy = y - lastY;
|
||||
|
||||
if (i == 0)
|
||||
data += 'M'; //emit absolute move on first pair of coordinates
|
||||
else if (isMove != lastIsMove)
|
||||
data += isMove ? 'm' : 'l';
|
||||
|
||||
data += dx + ',' + dy + ' ';
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
lastIsMove = isMove;
|
||||
}
|
||||
|
||||
svg += '\t<path transform="translate(' + -doodleBounds[0] + ',' + -doodleBounds[1] + ')" d="' + data + '" fill="none" stroke="black" stroke-width="2" />\n';
|
||||
|
||||
var fields = JSON.stringify({'height': numLayers, 'outlineShape': VERTICALSHAPE, 'twist': rStep});
|
||||
svg += '\t<!--<![CDATA[d3d-keys ' + fields + ']]>-->\n';
|
||||
|
||||
svg += '</svg>\n';
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
|
||||
//TODO: use local variables instead of _points,numLayers,VERTICALSHAPE and rStep so we can leave a current doodle in tact if an error occurs while parsing
|
||||
function loadFromSvg(svgData) {
|
||||
var mode = '', x = 0, y = 0;
|
||||
|
||||
console.log("loading " + svgData.length + " bytes of data...");
|
||||
|
||||
clearDoodle();
|
||||
|
||||
svgData = svgData.replace("M0,0 ",""); //RC: hack
|
||||
|
||||
var p = svgData.indexOf("<path");
|
||||
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
||||
p = svgData.indexOf('d="', p);
|
||||
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
||||
p += 3; //skip 'd="'
|
||||
|
||||
var skipSpace = function() { while (svgData.charAt(p) == ' ') p++; }
|
||||
var parseCommand = function() {
|
||||
while (true) {
|
||||
skipSpace();
|
||||
var c = svgData.charAt(p);
|
||||
if (c == 'M' || c == 'm' || c == 'L' || c == 'l') { //new command letter
|
||||
mode = c;
|
||||
} else if (c == '"') { //end of command chain
|
||||
return true;
|
||||
} else { //something else, must be a pair of coordinates...
|
||||
var tx = 0, ty = 0, numberEnd = 0, len = 0;
|
||||
// var firstComma = svgData.indexOf(',', p);
|
||||
// var firstSpace = svgData.indexOf(' ', p);
|
||||
|
||||
numberEnd = svgData.indexOf(',', p);
|
||||
|
||||
////// RC: if instead of a comma a space is used between a pair use that as a separator
|
||||
var firstSpace = svgData.indexOf(' ', p);
|
||||
if (firstSpace<numberEnd) numberEnd=firstSpace;
|
||||
//console.log('numberEnd',numberEnd,firstSpace);
|
||||
////////////////
|
||||
|
||||
if (numberEnd == -1) { console.log("could not find comma in coordinate pair"); return false; }
|
||||
len = numberEnd - p;
|
||||
tx = parseFloat(svgData.substr(p, len));
|
||||
p += len + 1;
|
||||
skipSpace();
|
||||
numberEnd = svgData.indexOf(' ', p);
|
||||
if (numberEnd == -1) { console.log("could not find space after coordinate pair"); return false; }
|
||||
len = numberEnd - p;
|
||||
ty = parseFloat(svgData.substr(p, len));
|
||||
p += len;
|
||||
|
||||
if (mode == 'M' || mode == 'L') {
|
||||
x = tx; y = ty;
|
||||
} else if (mode == 'm' || mode == 'l') {
|
||||
x += tx; y += ty;
|
||||
} else {
|
||||
console.log("loadFromSvg: found coordinate pair but mode was never set");
|
||||
return false;
|
||||
}
|
||||
|
||||
var isMove = mode == 'm' || mode == 'M';
|
||||
|
||||
//TODO: create script-wide function for adding points?
|
||||
//console.log("inserting "+x+","+y+" ",isMove);
|
||||
updatePrevX = x;
|
||||
updatePrevY = y;
|
||||
_points.push([x, y, isMove]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
|
||||
if (isMove) draw(x, y, -1);
|
||||
else draw(x, y);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
parseCommand(); //depends on value of p, so don't move this without taking that into consideration
|
||||
|
||||
const fieldDefMarker = "<!--<![CDATA[d3d-keys";
|
||||
p = svgData.indexOf(fieldDefMarker);
|
||||
if (p == -1) { console.log("loadFromSvg: could not find metadata marker"); return false; }
|
||||
p += fieldDefMarker.length;
|
||||
skipSpace();
|
||||
|
||||
var endP = svgData.indexOf("]]>-->", p);
|
||||
if (endP == -1) { console.log("loadFromSvg: could not find metadata end-marker"); return false; }
|
||||
var metaFields = JSON.parse(svgData.substr(p, endP - p));
|
||||
//TODO: log error and return false if parsing failed
|
||||
for (var k in metaFields) {
|
||||
var v = metaFields[k];
|
||||
switch (k) {
|
||||
case "height": numLayers = v; break;
|
||||
case "outlineShape": VERTICALSHAPE = v; break;
|
||||
case "twist": rStep = v; break;
|
||||
}
|
||||
}
|
||||
|
||||
renderToImageDataPreview();
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
// TODO assess if this var is still necessary
|
||||
var $displayThermometer = $("#thermometerContainer");
|
||||
|
||||
|
@ -29,7 +37,7 @@ function Thermometer() {
|
|||
];
|
||||
|
||||
this.init = function(targCanvas, targCanvasContainer) {
|
||||
console.log("Thermometer.init()");
|
||||
//console.log("Thermometer.init()");
|
||||
|
||||
this.$container = targCanvasContainer;
|
||||
|
||||
|
@ -40,7 +48,7 @@ function Thermometer() {
|
|||
|
||||
var self = this;
|
||||
this.thermoOverlayImg.onload = function() {
|
||||
console.log("canvasThermoOverlay img loaded");
|
||||
//console.log("canvasThermoOverlay img loaded");
|
||||
self.isInitted = true;
|
||||
self.update(self.currentTemperature, self.targetTemperature);
|
||||
};
|
||||
|
@ -57,7 +65,7 @@ function Thermometer() {
|
|||
|
||||
var progress = curr / targ;
|
||||
|
||||
progress = Math.min(progress, 1.0);
|
||||
// progress = Math.min(progress, 1.0);
|
||||
progress = Math.max(progress, 0);
|
||||
|
||||
var h = this.thermoHeight; // 94 // px
|
||||
|
@ -124,11 +132,15 @@ function Thermometer() {
|
|||
}
|
||||
}
|
||||
this.show = function() {
|
||||
this.$container.show();
|
||||
this.$container.addClass("thermometerAppear");
|
||||
// $("#progressbarCanvasContainer").addClass("thermometerAppear");
|
||||
// this.$container.show();
|
||||
this.enabled = true;
|
||||
}
|
||||
this.hide = function() {
|
||||
this.$container.hide();
|
||||
this.$container.removeClass("thermometerAppear");
|
||||
// $("#progressbarCanvasContainer").removeClass("thermometerAppear");
|
||||
// this.$container.hide();
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
var wordArtPopup;
|
||||
|
||||
function initWordArt() {
|
||||
$("body").append('<div id="svgfont" style="display:none"></div>');
|
||||
$("#svgfont").load("img/font.svg?");
|
||||
|
||||
wordArtPopup = new Popup($("#popupWordArt"),$("#popupMask"));
|
||||
$("#btnWordArtOk").on("onButtonClick",wordArtPopup.commit);
|
||||
$("#btnWordArtCancel").on("onButtonClick",wordArtPopup.cancel);
|
||||
$("#popupWordArt").bind("onPopupCancel", onWordArtCancel);
|
||||
$("#popupWordArt").bind("onPopupCommit", onWordArtOk);
|
||||
}
|
||||
|
||||
function showWordArtDialog() {
|
||||
buttonGroupAdd.hide();
|
||||
wordArtPopup.open();
|
||||
$("#txtWordArt").focus();
|
||||
$("#txtWordArt").val(""); //clear textbox
|
||||
}
|
||||
|
||||
function onWordArtCancel() {
|
||||
$("#txtWordArt").blur();
|
||||
}
|
||||
|
||||
function onWordArtOk() {
|
||||
$("#txtWordArt").blur();
|
||||
var s = $("#txtWordArt").val();
|
||||
drawTextOnCanvas(s);
|
||||
}
|
||||
|
||||
function drawTextOnCanvas(text) {
|
||||
if (typeof(text) == 'string') {
|
||||
var points = getStringAsPoints(text);
|
||||
|
||||
var bounds = getBounds(points);
|
||||
var scaleX = (canvasWidth-50) / bounds.width;
|
||||
var scaleY = (canvasHeight-50) / bounds.height;
|
||||
|
||||
var scale = Math.min(scaleX,scaleY);
|
||||
|
||||
scalePoints(points,scale);
|
||||
var bounds = getBounds(points);
|
||||
translatePoints(points,-bounds.x,-bounds.y); //left top of text is (0,0)
|
||||
translatePoints(points,-bounds.width/2,-bounds.height/2); //anchor point center
|
||||
translatePoints(points,canvasWidth/2,canvasHeight/2); //center in canvas
|
||||
|
||||
canvasDrawPoints(canvas,points);
|
||||
}
|
||||
}
|
||||
|
||||
function getStringAsPoints(text) {
|
||||
var allPoints = [];
|
||||
var xPos = 0;
|
||||
|
||||
for (var i=0; i<text.length; i++) {
|
||||
|
||||
if (text[i]==" ") { //space
|
||||
xPos += 8;
|
||||
} else { //other characters
|
||||
var path = getPathFromChar(text[i]);
|
||||
var points = getPointsFromPath(path);
|
||||
|
||||
if (points.length==0) continue;
|
||||
|
||||
translatePoints(points,-points[0][0],0);
|
||||
|
||||
var bounds = getBounds(points);
|
||||
|
||||
translatePoints(points,-bounds.x,0);
|
||||
translatePoints(points,xPos,0);
|
||||
|
||||
xPos+=bounds.width;
|
||||
xPos+=2;
|
||||
|
||||
for (var j=0; j<points.length; j++) {
|
||||
allPoints.push(points[j]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return allPoints;
|
||||
}
|
||||
|
||||
function getPathFromChar(ch) {
|
||||
var index = ch.charCodeAt(0)-33;
|
||||
var element = $("#svgfont path")[index];
|
||||
if (element==undefined) return "";
|
||||
return $("#svgfont path")[index].attributes["d"].nodeValue;
|
||||
}
|
||||
|
||||
function getPointsFromPath(path) {
|
||||
var points = [];
|
||||
var cmds = path.split(' ');
|
||||
var cursor = { x:0.0, y:0.0 };
|
||||
var move = false;
|
||||
var prevCmd = "";
|
||||
for (var i=0; i<cmds.length; i++) {
|
||||
var cmd = cmds[i];
|
||||
var xy = cmd.split(",");
|
||||
if (cmd=='m') move = true;
|
||||
if (xy.length==2) { // if there are two parts (a comma) we asume it's a l command. (So L is not supported)
|
||||
cursor.x += parseFloat(xy[0]);
|
||||
cursor.y += parseFloat(xy[1]);
|
||||
points.push([cursor.x,cursor.y,move]);
|
||||
move = false;
|
||||
} else if (prevCmd == "h"){
|
||||
cursor.x += parseFloat(cmd);
|
||||
points.push([cursor.x,cursor.y,move]);
|
||||
} else if (prevCmd == "v"){
|
||||
cursor.y += parseFloat(cmd);
|
||||
points.push([cursor.x,cursor.y,move]);
|
||||
} else if (prevCmd == "H"){
|
||||
cursor.x = parseFloat(cmd);
|
||||
points.push([cursor.x,cursor.y,move]);
|
||||
} else if (prevCmd == "V"){
|
||||
cursor.y = parseFloat(cmd);
|
||||
points.push([cursor.x,cursor.y,move]);
|
||||
}
|
||||
prevCmd = cmd;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function canvasDrawPoints(canvas,points) {
|
||||
beginShape();
|
||||
for (var i=0; i<points.length; i++) {
|
||||
var p = points[i];
|
||||
if (points[i][2]) shapeMoveTo(p[0],p[1]);
|
||||
else shapeLineTo(p[0],p[1]);
|
||||
}
|
||||
endShape();
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function ConfigAPI() {
|
||||
|
||||
var _wifiboxURL;
|
||||
var _wifiboxCGIBinURL;
|
||||
var _timeoutTime = 3000;
|
||||
var _saveSettingsTimeoutTime = 8000;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
|
||||
//console.log("ConfigAPI:init");
|
||||
|
||||
_wifiboxURL = wifiboxURL;
|
||||
_wifiboxCGIBinURL = wifiboxCGIBinURL;
|
||||
}
|
||||
this.loadAll = function(completeHandler,failedHandler) {
|
||||
//console.log("ConfigAPI:loadAll");
|
||||
$.ajax({
|
||||
url: _wifiboxURL + "/config/all",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
this.load = function(targetSettings,completeHandler,failedHandler) {
|
||||
//console.log("ConfigAPI:load");
|
||||
$.ajax({
|
||||
url: _wifiboxURL + "/config/",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
data: targetSettings,
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
this.save = function(newSettings,completeHandler,failedHandler) {
|
||||
//console.log("ConfigAPI:save");
|
||||
$.ajax({
|
||||
url: _wifiboxCGIBinURL + "/config",
|
||||
type: "POST",
|
||||
data: newSettings,
|
||||
dataType: 'json',
|
||||
timeout: _saveSettingsTimeoutTime,
|
||||
success: function(response){
|
||||
//console.log("ConfigAPI:save response: ",response);
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
this.resetAll = function(completeHandler,failedHandler) {
|
||||
//console.log("ConfigAPI:resetAll");
|
||||
$.ajax({
|
||||
url: _wifiboxCGIBinURL + "/config/resetall",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
function NetworkAPI() {
|
||||
|
||||
NetworkAPI.STATUS = {
|
||||
CONNECTING_FAILED: -1,
|
||||
NOT_CONNECTED: 0,
|
||||
CONNECTING: 1,
|
||||
CONNECTED: 2,
|
||||
CREATING: 3,
|
||||
CREATED: 4
|
||||
};
|
||||
|
||||
var _wifiboxURL;
|
||||
var _wifiboxCGIBinURL;
|
||||
var _timeoutTime = 3000;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
|
||||
//console.log("NetworkAPI:init");
|
||||
//console.log(" wifiboxURL: ",wifiboxURL);
|
||||
//console.log(" wifiboxCGIBinURL: ",wifiboxCGIBinURL);
|
||||
_wifiboxURL = wifiboxURL;
|
||||
_wifiboxCGIBinURL = wifiboxCGIBinURL;
|
||||
}
|
||||
this.scan = function(completeHandler,failedHandler) {
|
||||
//console.log("NetworkAPI:scan");
|
||||
$.ajax({
|
||||
url: _wifiboxURL + "/network/scan",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("NetworkAPI:scan response: ",response);
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
//console.log("NetworkAPI:scan failed: ",response);
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("NetworkAPI:scan failed");
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
this.status = function(completeHandler,failedHandler) {
|
||||
//console.log("NetworkAPI:status");
|
||||
$.ajax({
|
||||
url: _wifiboxURL + "/network/status",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("NetworkAPI:status response: ",response);
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
|
||||
this.associate = function(ssid,phrase,recreate) {
|
||||
//console.log("NetworkAPI:associate");
|
||||
var postData = {
|
||||
ssid:ssid,
|
||||
phrase:phrase,
|
||||
recreate:recreate
|
||||
};
|
||||
$.ajax({
|
||||
url: _wifiboxCGIBinURL + "/network/associate",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("NetworkAPI:associate response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("NetworkAPI:associate: timeout (normal behavior)");
|
||||
});
|
||||
};
|
||||
|
||||
this.openAP = function() {
|
||||
//console.log("NetworkAPI:openAP");
|
||||
$.ajax({
|
||||
url: _wifiboxCGIBinURL + "/network/openap",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("NetworkAPI:openAP response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("NetworkAPI:openAP: timeout (normal behavior)");
|
||||
});
|
||||
};
|
||||
|
||||
this.signin = function() {
|
||||
$.ajax({
|
||||
url: _wifiboxCGIBinURL + "/network/signin",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("NetworkAPI:signin response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("NetworkAPI:signin: failed");
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
function PrinterAPI() {
|
||||
|
||||
var _wifiboxURL;
|
||||
var _wifiboxCGIBinURL;
|
||||
var _timeoutTime = 3000;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
|
||||
//console.log("PrinterAPI:init");
|
||||
//console.log(" wifiboxURL: ",wifiboxURL);
|
||||
//console.log(" wifiboxCGIBinURL: ",wifiboxCGIBinURL);
|
||||
_wifiboxURL = wifiboxURL;
|
||||
_wifiboxCGIBinURL = wifiboxCGIBinURL;
|
||||
}
|
||||
|
||||
this.listAll = function(completeHandler,failedHandler) {
|
||||
//console.log("PrinterAPI:listAll");
|
||||
//console.log(" _wifiboxURL: ",_wifiboxURL);
|
||||
$.ajax({
|
||||
url: _wifiboxURL + "/printer/listall",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: _timeoutTime,
|
||||
success: function(response){
|
||||
//console.log("PrinterAPI response: ",response);
|
||||
if(response.status == "error" || response.status == "fail") {
|
||||
//console.log("PrinterAPI:listAll failed: ",response);
|
||||
if(failedHandler) failedHandler(response);
|
||||
} else {
|
||||
completeHandler(response.data);
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("PrinterAPI:listAll failed");
|
||||
if(failedHandler) failedHandler();
|
||||
});
|
||||
};
|
||||
}
|
|
@ -1,18 +1,19 @@
|
|||
var btnMoveUpInterval;
|
||||
var btnMoveDownInterval;
|
||||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var btnTwistLeftInterval;
|
||||
var btnTwistRightInterval;
|
||||
var twistIncrement = Math.PI/1800;
|
||||
|
||||
var btnOopsInterval;
|
||||
|
||||
var btnNew, btnPrevious, btnNext;
|
||||
var btnOops, btnStop, btnClear;
|
||||
var btnMoveUp, btnMoveDown, btnTwistLeft, btnTwistRight;
|
||||
var btnInfo, btnSettings;
|
||||
//var btnDebug; // debug
|
||||
var displayTemp, displayProgress;
|
||||
var btnNew, btnPrevious, btnNext, btnOops, btnStop, btnInfo;
|
||||
var btnSettings, btnWordArt;
|
||||
var btnToggleEdit, buttonGroupEdit, btnZoom, btnMove, btnRotate;
|
||||
var btnToggleVerticalShapes, btnHeight, btnTwist, btnShape, btnConv, btnStraight, btnSine, btnDiv;
|
||||
var buttonGroupAdd, popupWordArt;
|
||||
var btnScan, popupScan;
|
||||
|
||||
var state;
|
||||
var prevState;
|
||||
|
@ -21,352 +22,451 @@ var hasControl;
|
|||
var gcodeGenerateDelayer;
|
||||
var gcodeGenerateDelay = 50;
|
||||
|
||||
var preheatDelay;
|
||||
var preheatDelayTime = 15*1000;
|
||||
|
||||
var connectingHintDelay = null;
|
||||
var connectingHintDelayTime = 20 * 1000;
|
||||
|
||||
|
||||
function initButtonBehavior() {
|
||||
console.log("f:initButtonBehavior");
|
||||
console.log("f:initButtonBehavior");
|
||||
|
||||
// btnClear= $(".btnClear");
|
||||
btnOops = $(".btnOops");
|
||||
btnMoveUp = $("#btnMoveUp");
|
||||
btnMoveDown = $("#btnMoveDown");
|
||||
btnTwistLeft = $("#btnTwistLeft");
|
||||
btnTwistRight = $("#btnTwistRight");
|
||||
btnInfo = $(".btnInfo");
|
||||
btnSettings = $(".btnSettings");
|
||||
btnNew = $(".btnNew");
|
||||
btnPrint= $(".btnPrint");
|
||||
btnStop = $(".btnStop");
|
||||
displayTemp = $("#thermometerContainer");
|
||||
displayProgress = $("#printProgressContainer");
|
||||
btnOops = new Button("#btnOops");
|
||||
btnInfo = new Button("#btnInfo");
|
||||
btnSettings = new Button("#btnSettings");
|
||||
btnNew = new Button("#btnNew");
|
||||
btnPrint= new Button("#btnPrint");
|
||||
btnStop = new Button("#btnStop");
|
||||
btnPrevious = new Button("#btnPrevious");
|
||||
btnNext = new Button("#btnNext");
|
||||
btnSave = new Button("#btnSave");
|
||||
buttonGroupAdd = $("#buttonGroupAdd");
|
||||
btnShape = new Button("#btnShape");
|
||||
btnWordArt = new Button("#btnWordArt");
|
||||
btnScan = new Button("#btnScan");
|
||||
popupWordArt = $("#popupWordArt");
|
||||
popupShape = $("#popupShape");
|
||||
popupScan = $("#popupScan");
|
||||
popupMask = $("#popupMask");
|
||||
logoPanel = $("#logopanel");
|
||||
btnToggleEdit = new Button("#btnToggleEdit");
|
||||
buttonGroupEdit = $("#buttonGroupEdit");
|
||||
btnZoom = new Button("#btnZoom");
|
||||
btnMove = new Button("#btnMove");
|
||||
btnRotate = new Button("#btnRotate");
|
||||
btnToggleVerticalShapes = new Button("#btnToggleVerticalShapes");
|
||||
buttonGroupVerticalShapes = $("#buttonGroupVerticalShapes");
|
||||
btnHeight = new Button("#btnHeight");
|
||||
btnTwist = new Button("#btnTwist");
|
||||
btnStraight = new Button("#btnStraight");
|
||||
btnDiv = new Button("#btnDiv");
|
||||
btnConv = new Button("#btnConv");
|
||||
btnSine = new Button("#btnSine");
|
||||
btnAdd = new Button("#btnAdd");
|
||||
|
||||
btnPrevious = $(".btnPrevious");
|
||||
btnNext = $(".btnNext");
|
||||
$(".btn").Button(); //initalize other buttons
|
||||
|
||||
//debug
|
||||
//btnDebug = $(".debugBtn");
|
||||
logoPanel.on("onButtonClick", onLogo);
|
||||
btnNew.on("onButtonClick", onBtnNew);
|
||||
btnAdd.on("onButtonClick", onBtnAdd);
|
||||
btnWordArt.on("onButtonClick", onBtnWordArt);
|
||||
btnShape.on("onButtonClick", onBtnShape);
|
||||
btnScan.on("onButtonClick", onBtnScan);
|
||||
btnPrint.on("onButtonClick", print);
|
||||
btnStop.on("onButtonClick", stopPrint);
|
||||
btnSave.on("onButtonClick", saveSketch);
|
||||
btnPrevious.on("onButtonClick", previousSketch);
|
||||
btnNext.on("onButtonClick", nextSketch);
|
||||
btnOops.on("onButtonHold", onBtnOops);
|
||||
// vertical shape buttons
|
||||
btnToggleVerticalShapes.on("onButtonClick", onBtnToggleVerticalShapes);
|
||||
btnHeight.on("onButtonHold", onBtnHeight);
|
||||
btnTwist.on("onButtonHold", onBtnTwist);
|
||||
btnStraight.on("onButtonClick", onBtnStraight);
|
||||
btnDiv.on("onButtonClick", onBtnDiv);
|
||||
btnConv.on("onButtonClick", onBtnConv);
|
||||
btnSine.on("onButtonClick", onBtnSine);
|
||||
|
||||
btnNew.on('touchstart mousedown', clearDoodle);
|
||||
btnPrint.on('touchstart mousedown', print);
|
||||
btnToggleEdit.on("onButtonClick", onBtnToggleEdit);
|
||||
btnMove.on("onButtonHold", onBtnMove);
|
||||
btnZoom.on("onButtonHold", onBtnZoom);
|
||||
btnRotate.on("onButtonHold", onBtnRotate);
|
||||
|
||||
// not using these at the moment
|
||||
$("#btnPrevious").css("opacity", "0.3");
|
||||
btnNext.css("opacity", "0.3");
|
||||
$("#btnSave").css("opacity", "0.3");
|
||||
btnInfo.css("opacity", "0.3");
|
||||
//getSavedSketchStatus();
|
||||
listSketches();
|
||||
// setSketchModified(false);
|
||||
// updateSketchButtonStates();
|
||||
|
||||
// btnClear.click(function(e) {
|
||||
// e.preventDefault();
|
||||
// // console.log("clear");
|
||||
//
|
||||
// clearDoodle();
|
||||
// });
|
||||
function onBtnToggleVerticalShapes() {
|
||||
var btnImg;
|
||||
if (buttonGroupVerticalShapes.is(":hidden")) {
|
||||
btnImg = "img/buttons/btnArrowClose.png";
|
||||
} else {
|
||||
btnImg = "img/buttons/btnArrowOpen.png";
|
||||
}
|
||||
btnToggleVerticalShapes.attr("src",btnImg);
|
||||
|
||||
function startOops(e) {
|
||||
// console.log("btnOops mouse down");
|
||||
e.preventDefault();
|
||||
btnOopsInterval = setInterval( function() {
|
||||
oopsUndo();
|
||||
}, 1000/50);
|
||||
}
|
||||
function stopOops(e) {
|
||||
// console.log("btnOops mouse up");
|
||||
e.preventDefault();
|
||||
clearInterval(btnOopsInterval);
|
||||
}
|
||||
btnOops.on('touchstart', function(e) { startOops(e); });
|
||||
btnOops.on('touchend', function(e) { stopOops(e); });
|
||||
btnOops.mousedown(function(e) { startOops(e); });
|
||||
btnOops.mouseup(function(e) { stopOops(e); });
|
||||
buttonGroupVerticalShapes.fadeToggle(BUTTON_GROUP_SHOW_DURATION);
|
||||
}
|
||||
|
||||
function startMoveUp(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnMoveUp mouse down");
|
||||
previewUp(true);
|
||||
clearInterval(btnMoveUpInterval);
|
||||
btnMoveUpInterval = setInterval( function() {
|
||||
previewUp(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopMoveUp(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnMoveUp mouse up");
|
||||
clearInterval(btnMoveUpInterval);
|
||||
previewUp();
|
||||
}
|
||||
btnMoveUp.mousedown(function(e) { startMoveUp(e) });
|
||||
btnMoveUp.mouseup(function(e) { stopMoveUp(e) });
|
||||
btnMoveUp.on('touchstart', function(e) { startMoveUp(e) });
|
||||
btnMoveUp.on('touchend', function(e) { stopMoveUp(e) });
|
||||
function onLogo() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function startMoveDown(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnMoveDown mouse down");
|
||||
previewDown(true);
|
||||
clearInterval(btnMoveDownInterval);
|
||||
btnMoveDownInterval = setInterval( function() {
|
||||
previewDown(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopMoveDown(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnMoveDown mouse up");
|
||||
clearInterval(btnMoveDownInterval);
|
||||
previewDown();
|
||||
}
|
||||
btnMoveDown.mousedown(function(e) { startMoveDown(e) });
|
||||
btnMoveDown.mouseup(function(e) { stopMoveDown(e) });
|
||||
btnMoveDown.on('touchstart', function(e) { startMoveDown(e) });
|
||||
btnMoveDown.on('touchend', function(e) { stopMoveDown(e) });
|
||||
function onBtnAdd() {
|
||||
buttonGroupAdd.fadeToggle(BUTTON_GROUP_SHOW_DURATION);
|
||||
}
|
||||
|
||||
function startTwistLeft(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistLeft mouse down");
|
||||
previewTwistLeft(true);
|
||||
clearInterval(btnTwistLeftInterval);
|
||||
btnTwistLeftInterval = setInterval( function() {
|
||||
previewTwistLeft(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopTwistLeft(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistLeft mouse up");
|
||||
clearInterval(btnTwistLeftInterval);
|
||||
previewTwistLeft();
|
||||
}
|
||||
btnTwistLeft.mousedown(function(e) { startTwistLeft(e) });
|
||||
btnTwistLeft.mouseup(function(e) { stopTwistLeft(e) });
|
||||
btnTwistLeft.on('touchstart', function(e) { startTwistLeft(e) });
|
||||
btnTwistLeft.on('touchend', function(e) { stopTwistLeft(e) });
|
||||
function onBtnStraight() {
|
||||
setVerticalShape(verticalShapes.NONE);
|
||||
}
|
||||
function onBtnDiv() {
|
||||
setVerticalShape(verticalShapes.DIVERGING);
|
||||
}
|
||||
function onBtnConv() {
|
||||
setVerticalShape(verticalShapes.CONVERGING);
|
||||
}
|
||||
function onBtnSine() {
|
||||
setVerticalShape(verticalShapes.SINUS);
|
||||
}
|
||||
|
||||
function startTwistRight(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistRight mouse down");
|
||||
previewTwistRight(true);
|
||||
clearInterval(btnTwistRightInterval);
|
||||
btnTwistRightInterval = setInterval( function() {
|
||||
previewTwistRight(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopTwistRight(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistRight mouse up");
|
||||
clearInterval(btnTwistRightInterval);
|
||||
previewTwistRight();
|
||||
}
|
||||
btnTwistRight.mousedown(function(e) { startTwistRight(e) });
|
||||
btnTwistRight.mouseup(function(e) { stopTwistRight(e) });
|
||||
btnTwistRight.on('touchstart', function(e) { startTwistRight(e) });
|
||||
btnTwistRight.on('touchend', function(e) { stopTwistRight(e) });
|
||||
function hitTest(cursor,button,radius) {
|
||||
return distance(cursor.x,cursor.y,button.x,button.y)<radius;
|
||||
}
|
||||
|
||||
/*function openSettings() {
|
||||
console.log("f:openSettings()");
|
||||
$("#contentOverlay").fadeIn(1000, function() {
|
||||
loadSettings();
|
||||
});
|
||||
}*/
|
||||
btnSettings.bind('touchstart mousedown',function () {
|
||||
//e.preventDefault();
|
||||
//console.log("btnSettings clicked");
|
||||
settingsWindow.showSettings();
|
||||
});
|
||||
// btnSettings.on('touchend', function(e) {
|
||||
// e.preventDefault();
|
||||
// console.log("btnSettings touchend");
|
||||
// });
|
||||
|
||||
btnInfo.mouseup(function(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnInfo mouse up");
|
||||
});
|
||||
function onBtnToggleEdit() {
|
||||
var btnImg;
|
||||
if(buttonGroupEdit.is(":hidden")) {
|
||||
btnImg = "img/buttons/btnArrowClose.png";
|
||||
} else {
|
||||
btnImg = "img/buttons/btnArrowOpen.png";
|
||||
}
|
||||
btnToggleEdit.attr("src",btnImg);
|
||||
|
||||
// DEBUG
|
||||
/*
|
||||
// $(".agentInfo").css("display", "none");
|
||||
btnDebug.click(function(e) {
|
||||
console.log("debugClick");
|
||||
$(".agentInfo").toggleClass("agentInfoToggle");
|
||||
e.preventDefault();
|
||||
})
|
||||
//*/
|
||||
buttonGroupEdit.fadeToggle(BUTTON_GROUP_SHOW_DURATION);
|
||||
}
|
||||
function onBtnMove(e,cursor) {
|
||||
var w = btnMove.width();
|
||||
var h = btnMove.height();
|
||||
var speedX = (cursor.x-w/2)*0.3;
|
||||
var speedY = (cursor.y-h/2)*0.3;
|
||||
//console.log("move speed: ",speedX,speedY);
|
||||
moveShape(speedX,speedY);
|
||||
}
|
||||
function onBtnZoom(e,cursor) {
|
||||
var h = btnZoom.height();
|
||||
var multiplier = (h/2-cursor.y)*0.003 + 1;
|
||||
zoomShape(multiplier);
|
||||
}
|
||||
function onBtnRotate(e,cursor) {
|
||||
var h = btnZoom.height();
|
||||
var multiplier = (h/2-cursor.y)*0.003;
|
||||
rotateShape(-multiplier);
|
||||
}
|
||||
|
||||
//btnStop.on('touchstart mousedown',stopPrint);
|
||||
function onBtnHeight(e,cursor) {
|
||||
var h = btnHeight.height();
|
||||
if(cursor.y < h/2) {
|
||||
previewUp(true);
|
||||
} else {
|
||||
previewDown(true);
|
||||
}
|
||||
}
|
||||
function onBtnTwist(e,cursor) {
|
||||
var h = btnTwist.height();
|
||||
var multiplier = (cursor.y-h/2)*0.0005;
|
||||
previewTwist(multiplier,true);
|
||||
}
|
||||
|
||||
function onBtnOops(e) {
|
||||
oopsUndo();
|
||||
}
|
||||
|
||||
function onBtnNew(e) {
|
||||
newSketch();
|
||||
}
|
||||
|
||||
function onBtnWordArt(e) {
|
||||
showWordArtDialog();
|
||||
}
|
||||
|
||||
function onBtnShape(e) {
|
||||
showShapeDialog();
|
||||
buttonGroupAdd.fadeOut();
|
||||
}
|
||||
|
||||
function onBtnScan(e) {
|
||||
showScanDialog();
|
||||
buttonGroupAdd.fadeOut();
|
||||
}
|
||||
|
||||
btnSettings.on("onButtonClick", openSettingsWindow);
|
||||
|
||||
// 29-okt-2013 - we're not doing help for smartphones at the moment
|
||||
if (clientInfo.isSmartphone) {
|
||||
btnInfo.disable();
|
||||
} else {
|
||||
btnInfo.on("onButtonClick", function(e) {
|
||||
helpTours.startTour(helpTours.WELCOMETOUR);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function stopPrint() {
|
||||
console.log("f:stopPrint() >> sendPrintCommands = " + sendPrintCommands);
|
||||
if (!confirm("Weet je zeker dat je huidige print wilt stoppen?")) return;
|
||||
if (sendPrintCommands) printer.stop();
|
||||
//setState(Printer.STOPPING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.STOPPING_STATE);
|
||||
console.log("f:stopPrint() >> sendPrintCommands = " + sendPrintCommands);
|
||||
if (sendPrintCommands) printer.stop();
|
||||
//setState(Printer.STOPPING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.STOPPING_STATE);
|
||||
}
|
||||
|
||||
|
||||
function prevDoodle(e) {
|
||||
console.log("f:prevDoodle()");
|
||||
console.log("f:prevDoodle()");
|
||||
}
|
||||
function nextDoodle(e) {
|
||||
console.log("f:nextDoodle()");
|
||||
}
|
||||
|
||||
function print(e) {
|
||||
console.log("f:print() >> sendPrintCommands = " + sendPrintCommands);
|
||||
|
||||
//$(".btnPrint").css("display","none");
|
||||
//$(".btnPrint").css("display","none");
|
||||
|
||||
|
||||
if (_points.length > 2) {
|
||||
if (_points.length > 2) {
|
||||
|
||||
//setState(Printer.BUFFERING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.BUFFERING_STATE);
|
||||
|
||||
btnStop.css("display","none");
|
||||
|
||||
// we put the gcode generation in a little delay
|
||||
// so that for example the print button is disabled right away
|
||||
clearTimeout(gcodeGenerateDelayer);
|
||||
gcodeGenerateDelayer = setTimeout(function() {
|
||||
var gcode = generate_gcode();
|
||||
//startPrint(gencode);
|
||||
//setState(Printer.BUFFERING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.BUFFERING_STATE);
|
||||
|
||||
// we put the gcode generation in a little delay
|
||||
// so that for example the print button is disabled right away
|
||||
clearTimeout(gcodeGenerateDelayer);
|
||||
gcodeGenerateDelayer = setTimeout(function() {
|
||||
|
||||
var gcode = generate_gcode();
|
||||
if (sendPrintCommands) {
|
||||
printer.print(gcode);
|
||||
if(gcode.length > 0) {
|
||||
printer.print(gcode);
|
||||
} else {
|
||||
printer.overruleState(Printer.IDLE_STATE);
|
||||
printer.startStatusCheckInterval();
|
||||
}
|
||||
} else {
|
||||
console.log("sendPrintCommands is false: not sending print command to 3dprinter");
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
$("#textdump").text("");
|
||||
$("#textdump").text(gcode.join("\n"));
|
||||
}
|
||||
|
||||
}, gcodeGenerateDelay);
|
||||
} else {
|
||||
console.log("f:print >> not enough points!");
|
||||
}
|
||||
// if (debugMode) {
|
||||
// $("#textdump").text("");
|
||||
// $("#textdump").text(gcode.join("\n"));
|
||||
// }
|
||||
|
||||
//alert("Je tekening zal nu geprint worden");
|
||||
//$(".btnPrint").css("display","block");
|
||||
}, gcodeGenerateDelay);
|
||||
} else {
|
||||
console.log("f:print >> not enough points!");
|
||||
}
|
||||
|
||||
|
||||
// $.post("/doodle3d.of", { data:output }, function(data) {
|
||||
// btnPrint.disabled = false;
|
||||
// });
|
||||
// $.post("/doodle3d.of", { data:output }, function(data) {
|
||||
// btnPrint.disabled = false;
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
function clearMainView() {
|
||||
// console.log("f:clearMainView()");
|
||||
ctx.save();
|
||||
ctx.clearRect(0,0,canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
// console.log("f:clearMainView()");
|
||||
ctx.save();
|
||||
ctx.clearRect(0,0,canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
}
|
||||
function resetPreview() {
|
||||
// console.log("f:resetPreview()");
|
||||
// console.log("f:resetPreview()");
|
||||
|
||||
// clear preview canvas
|
||||
previewCtx.save();
|
||||
previewCtx.clearRect(0,0,canvas.width, canvas.height);
|
||||
previewCtx.restore();
|
||||
// clear preview canvas
|
||||
previewCtx.save();
|
||||
previewCtx.clearRect(0,0,canvas.width, canvas.height);
|
||||
previewCtx.restore();
|
||||
|
||||
// reset height and rotation to default values
|
||||
numLayers = previewDefaults.numLayers; // current number of preview layers
|
||||
rStep = previewDefaults.rotation; // Math.PI/180; //Math.PI/40; //
|
||||
// also make new Image, otherwise the previously cached preview can be redrawn with move up/down or twist left/right
|
||||
doodleImageCapture = new Image();
|
||||
|
||||
// reset height and rotation to default values
|
||||
numLayers = previewDefaults.numLayers; // current number of preview layers
|
||||
rStep = previewDefaults.rotation; // Math.PI/180; //Math.PI/40; //
|
||||
}
|
||||
|
||||
function oopsUndo() {
|
||||
// console.log("f:oopsUndo()");
|
||||
_points.pop();
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
// console.log("f:oopsUndo()");
|
||||
_points.pop();
|
||||
|
||||
if (clientInfo.isSmartphone) {
|
||||
// do not recalc the whole preview's bounds during undo if client device is a smartphone
|
||||
redrawDoodle(false);
|
||||
} else {
|
||||
// recalc the whole preview's bounds during if client device is not a smartphone
|
||||
redrawDoodle(true);
|
||||
}
|
||||
redrawPreview();
|
||||
}
|
||||
|
||||
function previewUp(redrawLess) {
|
||||
// console.log("f:previewUp()");
|
||||
if (numLayers < maxNumLayers) {
|
||||
numLayers++;
|
||||
}
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
// console.log("f:previewUp()");
|
||||
if (numLayers < maxNumLayers) {
|
||||
numLayers++;
|
||||
}
|
||||
setSketchModified(true);
|
||||
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
function previewDown(redrawLess) {
|
||||
// console.log("f:previewDown()");
|
||||
if (numLayers > minNumLayers) {
|
||||
numLayers--;
|
||||
}
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
// console.log("f:previewDown()");
|
||||
if (numLayers > minNumLayers) {
|
||||
numLayers--;
|
||||
}
|
||||
setSketchModified(true);
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
function previewTwistLeft(redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
// console.log("f:previewTwistLeft()");
|
||||
if (rStep > -previewRotationLimit) rStep -= twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
previewTwist(-twistIncrement,true)
|
||||
}
|
||||
function previewTwistRight(redrawLess) {
|
||||
// console.log("f:previewTwistRight()");
|
||||
if (rStep < previewRotationLimit) rStep += twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
previewTwist(twistIncrement,true)
|
||||
}
|
||||
function previewTwist(increment,redrawLess) {
|
||||
console.log("previewTwist: ",increment);
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
|
||||
rStep += increment;
|
||||
if(rStep < -previewRotationLimit) rStep = -previewRotationLimit;
|
||||
else if(rStep > previewRotationLimit) rStep = previewRotationLimit;
|
||||
|
||||
redrawRenderedPreview(redrawLess);
|
||||
setSketchModified(true);
|
||||
}
|
||||
|
||||
|
||||
function resetTwist() {
|
||||
rStep = 0;
|
||||
redrawRenderedPreview();
|
||||
setSketchModified(true);
|
||||
}
|
||||
|
||||
function update() {
|
||||
setState(printer.state,printer.hasControl);
|
||||
|
||||
thermometer.update(printer.temperature, printer.targetTemperature);
|
||||
//TODO: update progress
|
||||
progressbar.update(printer.currentLine, printer.totalLines);
|
||||
}
|
||||
|
||||
function setState(newState,newHasControl) { //TODO add hasControl
|
||||
function setState(newState,newHasControl) {
|
||||
if(newState == state && newHasControl == hasControl) return;
|
||||
|
||||
console.log("setState: ",state," > ",newState," ( ",newHasControl,")");
|
||||
prevState = state;
|
||||
|
||||
console.log("setState: " + prevState + " > " + newState + " ( " + newHasControl + ")");
|
||||
setDebugText("State: "+newState);
|
||||
|
||||
// print button
|
||||
var printEnabled = (newState == Printer.IDLE_STATE && newHasControl);
|
||||
if(printEnabled) {
|
||||
btnPrint.removeClass("disabled"); // enable print button
|
||||
btnPrint.unbind('touchstart mousedown');
|
||||
btnPrint.bind('touchstart mousedown',print);
|
||||
btnPrint.enable();
|
||||
} else {
|
||||
btnPrint.addClass("disabled"); // disable print button
|
||||
btnPrint.unbind('touchstart mousedown');
|
||||
btnPrint.disable();
|
||||
}
|
||||
|
||||
// stop button
|
||||
var stopEnabled = ((newState == Printer.PRINTING_STATE || newState == Printer.BUFFERING_STATE) && newHasControl);
|
||||
if(stopEnabled) {
|
||||
btnStop.removeClass("disabled");
|
||||
btnStop.unbind('touchstart mousedown');
|
||||
btnStop.bind('touchstart mousedown',stopPrint);
|
||||
btnStop.enable();
|
||||
} else {
|
||||
btnStop.addClass("disabled");
|
||||
btnStop.unbind('touchstart mousedown');
|
||||
btnStop.disable();
|
||||
}
|
||||
|
||||
// thermometer
|
||||
switch(newState) {
|
||||
case Printer.UNKNOWN_STATE:
|
||||
case Printer.DISCONNECTED_STATE:
|
||||
thermometer.hide();
|
||||
break;
|
||||
default:
|
||||
thermometer.show();
|
||||
break;
|
||||
case Printer.IDLE_STATE: /* fall-through */
|
||||
case Printer.BUFFERING_STATE: /* fall-through */
|
||||
case Printer.PRINTING_STATE: /* fall-through */
|
||||
case Printer.STOPPING_STATE:
|
||||
thermometer.show();
|
||||
break;
|
||||
default:
|
||||
thermometer.hide();
|
||||
break;
|
||||
}
|
||||
|
||||
// progress indicator
|
||||
switch(newState) {
|
||||
case Printer.PRINTING_STATE:
|
||||
displayProgress.show(); // TODO: Show progress
|
||||
break;
|
||||
default:
|
||||
displayProgress.hide(); // TODO: hide progress
|
||||
break;
|
||||
case Printer.PRINTING_STATE:
|
||||
progressbar.show();
|
||||
break;
|
||||
default:
|
||||
progressbar.hide();
|
||||
break;
|
||||
}
|
||||
|
||||
/* settings button */
|
||||
switch(newState) {
|
||||
case Printer.CONNECTING_STATE: /* fall-through */
|
||||
case Printer.IDLE_STATE:
|
||||
btnSettings.enable();
|
||||
break;
|
||||
case Printer.WIFIBOX_DISCONNECTED_STATE: /* fall-through */
|
||||
case Printer.BUFFERING_STATE: /* fall-through */
|
||||
case Printer.PRINTING_STATE: /* fall-through */
|
||||
case Printer.STOPPING_STATE:
|
||||
btnSettings.disable();
|
||||
break;
|
||||
default:
|
||||
btnSettings.enable();
|
||||
break;
|
||||
}
|
||||
|
||||
/* save, next and prev buttons */
|
||||
switch(newState) {
|
||||
case Printer.WIFIBOX_DISCONNECTED_STATE:
|
||||
btnPrevious.disable();
|
||||
btnNext.disable()
|
||||
btnSave.disable();
|
||||
break;
|
||||
default:
|
||||
// updatePrevNextButtonState();
|
||||
updateSketchButtonStates();
|
||||
if (isModified) btnSave.enable();
|
||||
break;
|
||||
}
|
||||
|
||||
if(connectingHintDelay && newState != Printer.CONNECTING_STATE) {
|
||||
clearTimeout(connectingHintDelay);
|
||||
connectingHintDelay = null;
|
||||
}
|
||||
|
||||
if(newState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||
message.set("Lost connection to WiFi box",Message.ERROR);
|
||||
} else if(prevState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||
message.set("Connected to WiFi box",Message.INFO,true);
|
||||
} else if(newState == Printer.DISCONNECTED_STATE) {
|
||||
message.set("Printer disconnected",Message.WARNING,true);
|
||||
} else if(newState == Printer.CONNECTING_STATE) {
|
||||
message.set("Printer connecting...",Message.INFO,false);
|
||||
if (prevState != Printer.CONNECTING_STATE) { //enable 'watchdog' if we entered from a different state
|
||||
clearTimeout(connectingHintDelay);
|
||||
connectingHintDelay = setTimeout(function() {
|
||||
message.set("Printer still not connected, did you<br/>select the correct printer type?", Message.WARNING, false);
|
||||
connectingHintDelay = null;
|
||||
}, connectingHintDelayTime);
|
||||
}
|
||||
} else if(prevState == Printer.DISCONNECTED_STATE && newState == Printer.IDLE_STATE ||
|
||||
prevState == Printer.UNKNOWN_STATE && newState == Printer.IDLE_STATE ||
|
||||
prevState == Printer.CONNECTING_STATE && newState == Printer.IDLE_STATE) {
|
||||
message.set("Printer connected",Message.INFO,true);
|
||||
console.log(" preheat: ",settings["printer.heatup.enabled"]);
|
||||
if(settings["printer.heatup.enabled"]) {
|
||||
// HACK: we delay the preheat because the makerbot driver needs time to connect
|
||||
clearTimeout(preheatDelay);
|
||||
preheatDelay = setTimeout(printer.preheat,preheatDelayTime); // retry after delay
|
||||
}
|
||||
} else if(prevState == Printer.PRINTING_STATE && newState == Printer.STOPPING_STATE) {
|
||||
console.log("stopmsg show");
|
||||
message.set("Printer stopping",Message.INFO,false);
|
||||
} else if(prevState == Printer.STOPPING_STATE && newState == Printer.IDLE_STATE) {
|
||||
console.log("stopmsg hide");
|
||||
message.hide();
|
||||
}
|
||||
|
||||
prevState = state;
|
||||
state = newState;
|
||||
hasControl = newHasControl;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* VARS
|
||||
|
@ -29,13 +37,15 @@ var movementCounter = 0;
|
|||
var drawVariableLineWeight = false; // set to true to have the momentum of the mouse/touch movement result in larger/smaller strokes
|
||||
var lineweight = 2;
|
||||
|
||||
var isModified = false;
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* INIT
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function initDoodleDrawing() {
|
||||
console.log("f:initDoodleDrawing()");
|
||||
//console.log("f:initDoodleDrawing()");
|
||||
|
||||
$canvas = $("#mycanvas");
|
||||
canvas = $canvas[0];
|
||||
|
@ -69,7 +79,7 @@ function initDoodleDrawing() {
|
|||
// drawCanvas = $(".drawareacontainer");
|
||||
drawCanvas = $("#mycanvasContainer"); // $("#drawAreaContainer")
|
||||
|
||||
console.log("drawCanvasTopLeftCoords: " + drawCanvasTopLeftCoords);
|
||||
//console.log("drawCanvasTopLeftCoords: " + drawCanvasTopLeftCoords);
|
||||
// drawCanvasTopLeftCoords[0] = drawCanvas.css("left").match(/[0-9]/g).join("");
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas.css("top").match(/[0-9]/g).join("");
|
||||
drawCanvasTopLeftCoords[0] = drawCanvas.offset().left;
|
||||
|
@ -77,8 +87,8 @@ function initDoodleDrawing() {
|
|||
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
|
||||
|
||||
console.log("f:initDoodleDrawing() >> canvasWidth: " + canvasWidth);
|
||||
console.log("f:initDoodleDrawing() >> canvasHeight: " + canvasHeight);
|
||||
//console.log("f:initDoodleDrawing() >> canvasWidth: " + canvasWidth);
|
||||
//console.log("f:initDoodleDrawing() >> canvasHeight: " + canvasHeight);
|
||||
|
||||
}
|
||||
|
||||
|
@ -87,51 +97,66 @@ function initDoodleDrawing() {
|
|||
* CANVAS DRAWING FUNCTION
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function draw(_x, _y, _width) {
|
||||
// console.log("f:draw() >> _width: " + _width);
|
||||
|
||||
if (prevX == 0 && prevY ==0) {
|
||||
//If _width is not specified, it is calculated from the distance between this and the previous point.
|
||||
//If _width is negative, the path is 'floating', and only drawn if the setting printer.bottomEnableTraveling is true.
|
||||
function draw(_x, _y, _width) {
|
||||
//console.log("canvasDrawing:draw");
|
||||
//console.log("f:draw() >> _width: " + _width);
|
||||
|
||||
if (prevX == 0 && prevY == 0) {
|
||||
prevX = _x;
|
||||
prevY = _y;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(_x, _y);
|
||||
|
||||
if (_width != undefined) {
|
||||
ctx.lineWidth = _width;
|
||||
} else {
|
||||
if (drawVariableLineWeight) {
|
||||
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
|
||||
if (dist < 10) {
|
||||
lineweight += .25;
|
||||
} else if (dist < 20) {
|
||||
lineweight += .5;
|
||||
} else if (dist < 30) {
|
||||
lineweight += .75;
|
||||
} else if (dist < 50) {
|
||||
lineweight += 1;
|
||||
} else if (dist < 80) {
|
||||
lineweight += 1.5;
|
||||
} else if (dist < 120) {
|
||||
lineweight += 2.25;
|
||||
} else if (dist < 170) {
|
||||
lineweight += 3.5;
|
||||
} else {
|
||||
lineweight += 2;
|
||||
}
|
||||
lineweight = Math.min(lineweight, 30);
|
||||
lineweight *= 0.90;
|
||||
lineweight = Math.max(lineweight, 1.0);
|
||||
var lineWeight = null;
|
||||
if (_width != undefined && _width < 0) {
|
||||
if (settings['printer.bottomEnableTraveling']) {
|
||||
ctx.moveTo(_x, _y);
|
||||
} else {
|
||||
lineweight = 2;
|
||||
lineWeight = 0.5;
|
||||
}
|
||||
} else {
|
||||
if (_width != undefined) {
|
||||
lineWeight = _width;
|
||||
} else {
|
||||
if (drawVariableLineWeight) {
|
||||
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
|
||||
if (dist < 10) {
|
||||
lineWeight += .25;
|
||||
} else if (dist < 20) {
|
||||
lineWeight += .5;
|
||||
} else if (dist < 30) {
|
||||
lineWeight += .75;
|
||||
} else if (dist < 50) {
|
||||
lineWeight += 1;
|
||||
} else if (dist < 80) {
|
||||
lineWeight += 1.5;
|
||||
} else if (dist < 120) {
|
||||
lineWeight += 2.25;
|
||||
} else if (dist < 170) {
|
||||
lineWeight += 3.5;
|
||||
} else {
|
||||
lineWeight += 2;
|
||||
}
|
||||
lineWeight = Math.min(lineWeight, 30);
|
||||
lineWeight *= 0.90;
|
||||
lineWeight = Math.max(lineWeight, 1.0);
|
||||
} else {
|
||||
lineWeight = 2;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineweight;
|
||||
}
|
||||
ctx.lineCap = 'round';
|
||||
ctx.stroke();
|
||||
|
||||
if (lineWeight != null) {
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineWidth = lineWeight;
|
||||
ctx.lineTo(_x, _y);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
prevX = _x;
|
||||
prevY = _y;
|
||||
|
@ -144,7 +169,9 @@ function draw(_x, _y, _width) {
|
|||
*
|
||||
* * * * * * * * * */
|
||||
function clearDoodle() {
|
||||
console.log("f:clearDoodle");
|
||||
//console.log("f:clearDoodle");
|
||||
|
||||
//updatePrevNextButtonStateOnClear();
|
||||
|
||||
_points = [];
|
||||
|
||||
|
@ -162,10 +189,24 @@ function clearDoodle() {
|
|||
clearMainView();
|
||||
resetPreview();
|
||||
resetVerticalShapes();
|
||||
|
||||
setSketchModified(false);
|
||||
// updateSketchButtonStates();
|
||||
}
|
||||
|
||||
function redrawDoodle() {
|
||||
console.log("f:redrawDoodle()");
|
||||
function redrawDoodle(recalcBoundsAndTransforms) {
|
||||
//console.log("canvasDrawing:redrawDoodle");
|
||||
if (recalcBoundsAndTransforms == undefined) recalcBoundsAndTransforms = false;
|
||||
// console.log("f:redrawDoodle() >> recalcBoundsAndTransforms = " + recalcBoundsAndTransforms);
|
||||
|
||||
if (recalcBoundsAndTransforms == true) {
|
||||
doodleBounds = [-1, -1, -1, -1]; // left, top, right, bottom
|
||||
doodleTransform = [0, 0, 1.0, 1.0]; // [ x, y, scaleX, scaleY ]
|
||||
for (var i = 0; i < _points.length; i++) {
|
||||
adjustBounds(_points[i][0], _points[i][1]);
|
||||
adjustPreviewTransformation();
|
||||
}
|
||||
}
|
||||
|
||||
clearMainView();
|
||||
|
||||
|
@ -175,16 +216,17 @@ function redrawDoodle() {
|
|||
for (var i = 0; i < _points.length; i++) {
|
||||
// console.log(" drawing points " + _points[i]);
|
||||
if (_points[i][2] == true) {
|
||||
draw(_points[i][0], _points[i][1], 0.5);
|
||||
draw(_points[i][0], _points[i][1], -1);
|
||||
} else {
|
||||
draw(_points[i][0], _points[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks if x,y is outside doodleBounds, if so update
|
||||
function adjustBounds(x, y) {
|
||||
//console.log("canvasDrawing:adjustBounds");
|
||||
var newPointsOutsideOfCurrentBounds = false;
|
||||
console.log("f:adjustBounds("+x+","+y+")");
|
||||
// console.log("f:adjustBounds("+x+","+y+")");
|
||||
|
||||
if (doodleBounds[0] == -1) {
|
||||
// if doodleBounds[0] is -1 then it isn't initted yet, so x and y are both the min and max vals
|
||||
|
@ -212,35 +254,14 @@ function redrawDoodle() {
|
|||
doodleBounds[3] = y;
|
||||
newPointsOutsideOfCurrentBounds = true;
|
||||
}
|
||||
// doodleBounds[0] = Math.min(doodleBounds[0], x); // left
|
||||
// doodleBounds[2] = Math.max(doodleBounds[2], x); // right
|
||||
//
|
||||
// doodleBounds[1] = Math.min(doodleBounds[1], y); // top
|
||||
// doodleBounds[3] = Math.max(doodleBounds[3], y); // bottom
|
||||
|
||||
// draw the bounding rect (DEBUG)
|
||||
/*
|
||||
ctx.beginPath();
|
||||
ctx.rect(doodleBounds[0],doodleBounds[1], doodleBounds[2] - doodleBounds[0], doodleBounds[3] - doodleBounds[1]);
|
||||
ctx.lineWidth = .2;
|
||||
ctx.strokeStyle = "#333"
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
//*/
|
||||
|
||||
// console.log(" new bounds: " + doodleBounds);
|
||||
|
||||
return newPointsOutsideOfCurrentBounds;
|
||||
return newPointsOutsideOfCurrentBounds;
|
||||
}
|
||||
|
||||
// does what exactly?
|
||||
function adjustPreviewTransformation() {
|
||||
// console.log("f:adjustPreviewTransformation()");
|
||||
//console.log("canvasDrawing:adjustPreviewTransformation");
|
||||
|
||||
// doodleTransform[0] = doodleBounds[0] - (doodleBounds[2] - doodleBounds[0]) / 2;
|
||||
// doodleTransform[1] = doodleBounds[1] - (doodleBounds[3] - doodleBounds[1]) / 2;
|
||||
// doodleTransform[0] = doodleBounds[0] - ((doodleBounds[2] - doodleBounds[0]) / 2);
|
||||
// doodleTransform[1] = doodleBounds[1] - ((doodleBounds[3] - doodleBounds[1]) / 2);
|
||||
doodleTransform[0] = doodleBounds[0];
|
||||
doodleTransform[1] = doodleBounds[1];
|
||||
|
||||
|
@ -269,21 +290,18 @@ function adjustPreviewTransformation() {
|
|||
*
|
||||
* * * * * * * * * */
|
||||
function onCanvasMouseDown(e) {
|
||||
// console.log("onmousedown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
|
||||
// console.log("onmousedown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
|
||||
// console.log("onmousedown >> e: " + e);
|
||||
// console.log(e);
|
||||
//console.log("canvasDrawing:onCanvasMouseDown");
|
||||
setSketchModified(true);
|
||||
|
||||
// console.log("f:onCanvasMouseDown()");
|
||||
// console.log("onCanvasMouseDown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
|
||||
// console.log("onCanvasMouseDown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
|
||||
// console.log("onCanvasMouseDown >> e: " , e);
|
||||
dragging = true;
|
||||
|
||||
prevCountingTime = new Date().getTime();
|
||||
movementCounter = 0
|
||||
|
||||
// _points.push([e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, true]);
|
||||
// adjustBounds(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
|
||||
// adjustPreviewTransformation();
|
||||
// draw(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, 0.5);
|
||||
|
||||
var x, y;
|
||||
if (e.offsetX != undefined) {
|
||||
x = e.offsetX;
|
||||
|
@ -297,13 +315,17 @@ function onCanvasMouseDown(e) {
|
|||
_points.push([x, y, true]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y, 0.5);
|
||||
draw(x, y, -1);
|
||||
}
|
||||
|
||||
var prevPoint = {x:-1, y:-1};
|
||||
function onCanvasMouseMove(e) {
|
||||
//console.log("canvasDrawing:onCanvasMouseMove");
|
||||
// console.log("f:onCanvasMouseMove()");
|
||||
if (!dragging) return;
|
||||
|
||||
setSketchModified(true);
|
||||
|
||||
// console.log("onmousemove");
|
||||
|
||||
var x, y;
|
||||
|
@ -315,25 +337,17 @@ function onCanvasMouseMove(e) {
|
|||
y = e.layerY;
|
||||
}
|
||||
|
||||
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
||||
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
||||
if (dist > 5) { // replace by setting: doodle3d.simplify.minDistance
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
} else {
|
||||
var prevPresent = prevPoint.x != -1 || prevPoint.y != -1;
|
||||
var dist = prevPresent ? Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2)) : undefined;
|
||||
if (!prevPresent || dist > 5) { // replace dist check by setting: doodle3d.simplify.minDistance
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
|
||||
|
||||
// DEBUG
|
||||
// $("#textdump").text("");
|
||||
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
|
||||
|
@ -342,20 +356,13 @@ function onCanvasMouseMove(e) {
|
|||
if (new Date().getTime() - prevRedrawTime > redrawInterval) {
|
||||
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
|
||||
prevRedrawTime = new Date().getTime();
|
||||
if (_points.length < 50) {
|
||||
// Keep fully updating the preview if device is not a smartphone.
|
||||
// (An assumption is made here that anything greater than a smartphone will have sufficient
|
||||
// performance to always redraw the preview.)
|
||||
if (_points.length < 50 || !clientInfo.isSmartphone) {
|
||||
redrawPreview();
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
/*
|
||||
if (_points.length - prevUpdateFullPreview > prevUpdateFullPreviewInterval) {
|
||||
console.log("f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview");
|
||||
redrawPreview();
|
||||
prevUpdateFullPreview = _points.length;
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
}
|
||||
//*/
|
||||
// redrawPreview();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -366,11 +373,11 @@ function onCanvasMouseUp(e) {
|
|||
// console.log("f:onCanvasMouseUp()");
|
||||
// console.log("onmouseup");
|
||||
dragging = false;
|
||||
console.log("doodleBounds: " + doodleBounds);
|
||||
console.log("doodleTransform: " + doodleTransform);
|
||||
//console.log("doodleBounds: " + doodleBounds);
|
||||
//console.log("doodleTransform: " + doodleTransform);
|
||||
// ctx.stroke();
|
||||
|
||||
console.log("_points.length :" + _points.length);
|
||||
//console.log("_points.length :" + _points.length);
|
||||
// console.log(_points);
|
||||
|
||||
// DEBUG
|
||||
|
@ -383,8 +390,10 @@ function onCanvasMouseUp(e) {
|
|||
}
|
||||
|
||||
function onCanvasTouchDown(e) {
|
||||
setSketchModified(true);
|
||||
|
||||
e.preventDefault();
|
||||
console.log("f:onCanvasTouchDown >> e: " , e);
|
||||
//console.log("f:onCanvasTouchDown >> e: " , e);
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
||||
var x = e.touches[0].pageX - drawCanvasTopLeftCoords[0];
|
||||
|
@ -397,7 +406,7 @@ function onCanvasTouchDown(e) {
|
|||
_points.push([x, y, true]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y, .5);
|
||||
draw(x, y, -1);
|
||||
|
||||
movementCounter = 0;
|
||||
|
||||
|
@ -405,6 +414,9 @@ function onCanvasTouchDown(e) {
|
|||
}
|
||||
|
||||
function onCanvasTouchMove(e) {
|
||||
//console.log("canvasDrawing:onCanvasTouchMove");
|
||||
setSketchModified(true);
|
||||
|
||||
e.preventDefault();
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
||||
|
@ -415,21 +427,13 @@ function onCanvasTouchMove(e) {
|
|||
// var x = e.touches[0].layerX;
|
||||
// var y = e.touches[0].layerY;
|
||||
|
||||
console.log("f:onCanvasTouchMove >> x,y = "+x+","+y+" , e: " , e);
|
||||
//console.log("f:onCanvasTouchMove >> x,y = "+x+","+y+" , e: " , e);
|
||||
|
||||
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
||||
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
||||
if (dist > 5) {
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
} else {
|
||||
var prevPresent = prevPoint.x != -1 || prevPoint.y != -1;
|
||||
var dist = prevPresent ? Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2)) : undefined;
|
||||
if (!prevPresent || dist > 5) { // replace dist check by setting: doodle3d.simplify.minDistance
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
|
@ -468,12 +472,12 @@ function onCanvasTouchMove(e) {
|
|||
}
|
||||
|
||||
function onCanvasTouchEnd(e) {
|
||||
console.log("f:onCanvasTouchEnd()");
|
||||
console.log("doodleBounds: " + doodleBounds);
|
||||
console.log("doodleTransform: " + doodleTransform);
|
||||
//console.log("f:onCanvasTouchEnd()");
|
||||
//console.log("doodleBounds: " + doodleBounds);
|
||||
//console.log("doodleTransform: " + doodleTransform);
|
||||
// ctx.stroke();
|
||||
|
||||
console.log("_points.length :" + _points.length);
|
||||
//console.log("_points.length :" + _points.length);
|
||||
|
||||
// redrawPreview();
|
||||
renderToImageDataPreview();
|
||||
|
@ -481,4 +485,4 @@ function onCanvasTouchEnd(e) {
|
|||
|
||||
function prevent(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function setTemperature(callback) {
|
||||
|
||||
if (callback != undefined) callback();
|
||||
|
@ -7,4 +15,4 @@ function setTemperature(callback) {
|
|||
|
||||
if (callback != undefined) callback();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,138 +1,70 @@
|
|||
var gcodeStart = [];
|
||||
gcodeStart.push(";Generated with Doodle3D");
|
||||
gcodeStart.push("G21"); // metric values
|
||||
gcodeStart.push("G91"); // relative positioning
|
||||
gcodeStart.push("M107"); // start with the fan off
|
||||
gcodeStart.push("G28 X0 Y0"); // move X/Y to min endstops
|
||||
gcodeStart.push("G28 Z0"); // move Z to min endstops
|
||||
gcodeStart.push("G1 Z15 F9000"); // move the platform down 15mm
|
||||
gcodeStart.push("G92 E0"); // zero the extruded length
|
||||
gcodeStart.push("G1 F200 E10"); // extrude 10mm of feed stock
|
||||
gcodeStart.push("G92 E0"); // zero the extruded length again
|
||||
//gcodeStart.push("G92 X-100 Y-100 E0"); // zero the extruded length again and make center the start position
|
||||
gcodeStart.push("G1 F9000");
|
||||
gcodeStart.push("G90"); // absolute positioning
|
||||
gcodeStart.push("M117 Printing Doodle... "); // display message (20 characters to clear whole screen)
|
||||
|
||||
var gcodeEnd= [];
|
||||
gcodeEnd.push("M107"); // fan off
|
||||
gcodeEnd.push("G91"); // relative positioning
|
||||
gcodeEnd.push("G1 E-1 F300"); // retract the filament a bit before lifting the nozzle, to release some of the pressure
|
||||
gcodeEnd.push("G1 Z+0.5 E-5 X-20 Y-20 F9000"); // move Z up a bit and retract filament even more
|
||||
gcodeEnd.push("G28 X0 Y0"); // move X/Y to min endstops, so the head is out of the way
|
||||
gcodeEnd.push("M84"); // disable axes / steppers
|
||||
gcodeEnd.push("G90"); // absolute positioning
|
||||
gcodeEnd.push("M117 Done "); // display message (20 characters to clear whole screen)
|
||||
|
||||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var MAX_POINTS_TO_PRINT = 200000
|
||||
var gcode = [];
|
||||
function generate_gcode(callback) {
|
||||
|
||||
function generate_gcode() {
|
||||
console.log("f:generategcode()");
|
||||
|
||||
var startGcode = [];
|
||||
var endGcode = [];
|
||||
|
||||
// TODO 2013-09-18 evaluate if this should stay here
|
||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
||||
var gCodeOffsetX = 110; // mm
|
||||
var gCodeOffsetY = 110; // mm
|
||||
|
||||
// get gcode start statements
|
||||
if ($("#startgcode").val().trim().length != 0) {
|
||||
console.log(" found contents for start-gcode in settings.html")
|
||||
startGcode = $("#startgcode").val().trim().split("\n");
|
||||
} else {
|
||||
console.log(" no start-gcode in settings.html, using defaults")
|
||||
startGcode = startGcode.concat(gcodeStart);
|
||||
}
|
||||
|
||||
console.log("f:generate_gcode() >> startGcode:");
|
||||
console.log(startGcode);
|
||||
console.log("");
|
||||
console.log("f:generate_gcode() >> endGcode:");
|
||||
console.log(endGcode);
|
||||
|
||||
// get gcode end statements
|
||||
if ($("#endgcode").val().trim().length != 0) {
|
||||
console.log(" found contents for end-gcode in settings.html")
|
||||
endGcode = $("#endgcode").val().trim().split("\n");
|
||||
} else {
|
||||
console.log(" no end-gcode in settings.html, using defaults")
|
||||
endGcode = endGcode.concat(gcodeEnd);
|
||||
}
|
||||
|
||||
gcode = [];
|
||||
|
||||
console.log("settings: ",settings);
|
||||
var speed = settings["printer.speed"]
|
||||
var speed = settings["printer.speed"];
|
||||
var normalSpeed = speed;
|
||||
var bottomSpeed = speed*0.5;
|
||||
var bottomSpeed = settings["printer.bottomLayerSpeed"];
|
||||
var firstLayerSlow = settings["printer.firstLayerSlow"];
|
||||
var bottomFlowRate = settings["printer.bottomFlowRate"];
|
||||
var bottomEnableTraveling = settings["printer.bottomEnableTraveling"];
|
||||
var travelSpeed = settings["printer.travelSpeed"]
|
||||
var filamentThickness = settings["printer.filamentThickness"];
|
||||
var wallThickness = settings["printer.wallThickness"];
|
||||
var screenToMillimeterScale = settings["printer.screenToMillimeterScale"];
|
||||
var layerHeight = settings["printer.layerHeight"];
|
||||
var maxObjectHeight = settings["printer.maxObjectHeight"];
|
||||
var temperature = settings["printer.temperature"];
|
||||
var bedTemperature = settings["printer.bed.temperature"];
|
||||
var useSubLayers = settings["printer.useSubLayers"];
|
||||
var enableTraveling = settings["printer.enableTraveling"];
|
||||
var retractionEnabled = settings["printer.retraction.enabled"];
|
||||
var retractionspeed = settings["printer.retraction.speed"];
|
||||
var retractionminDistance = settings["printer.retraction.minDistance"];
|
||||
var retractionamount = settings["printer.retraction.amount"];
|
||||
var preheatTemperature = settings["printer.heatup.temperature"];
|
||||
var preheatBedTemperature = settings["printer.heatup.bed.temperature"];
|
||||
var printerDimensionsX = settings["printer.dimensions.x"];
|
||||
var printerDimensionsY = settings["printer.dimensions.y"];
|
||||
var printerDimensionsZ = settings["printer.dimensions.z"];
|
||||
|
||||
/*
|
||||
console.log("f:generate_gcode >> EFFE CHECKEN:");
|
||||
console.log(" speed: " + speed);
|
||||
console.log(" travelSpeed: " + travelSpeed);
|
||||
console.log(" filamentThickness: " + filamentThickness);
|
||||
console.log(" wallThickness: " + wallThickness);
|
||||
console.log(" screenToMillimeterScale: " + screenToMillimeterScale);
|
||||
console.log(" layerHeight: " + layerHeight);
|
||||
console.log(" objectHeight: " + objectHeight);
|
||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
||||
console.log(" temperature: " + temperature);
|
||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
||||
console.log(" useSubLayers: " + useSubLayers);
|
||||
console.log(" enableTraveling: " + enableTraveling);
|
||||
console.log(" retractionspeed: " + retractionspeed);
|
||||
console.log(" retractionminDistance: " + retractionminDistance);
|
||||
console.log(" retractionamount: " + retractionamount);
|
||||
console.log("");
|
||||
//*/
|
||||
var gCodeOffsetX = printerDimensionsX/2;
|
||||
var gCodeOffsetY = printerDimensionsY/2;
|
||||
|
||||
var startCode = generateStartCode();
|
||||
var endCode = generateEndCode();
|
||||
|
||||
// max amount of real world layers
|
||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
var layers = printerDimensionsZ / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
|
||||
// translate numLayers in preview to objectHeight in real world
|
||||
//objectHeight = Math.ceil(numLayers / 5); // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
||||
//objectHeight = numLayers; // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
||||
objectHeight = Math.round(numLayers/maxNumLayers*maxObjectHeight);
|
||||
objectHeight = Math.round(numLayers/maxNumLayers*printerDimensionsZ);
|
||||
|
||||
// translate preview rotation (per layer) to real world rotation
|
||||
var rStepGCode = rStep * maxNumLayers/layers; ///maxNumLayers*maxObjectHeight;
|
||||
|
||||
// correct direction
|
||||
rStepGCode = -rStepGCode;
|
||||
|
||||
// todo hier een array van PATHS maken wat de losse paths zijn
|
||||
|
||||
// copy array without reference -> http://stackoverflow.com/questions/9885821/copying-of-an-array-of-objects-to-another-array-without-object-reference-in-java
|
||||
var points = JSON.parse(JSON.stringify(_points));
|
||||
console.log("f:generategcode() >> points.length: " + points.length);
|
||||
|
||||
// console.log("f:generategcode() >> paths: " + paths.toString());
|
||||
// console.log("paths.toString(): " + paths.toString());
|
||||
// return;
|
||||
|
||||
console.log("printer temperature: ",temperature);
|
||||
gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
|
||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
||||
// add gcode begin commands
|
||||
gcode = gcode.concat(startGcode);
|
||||
gcode = gcode.concat(startCode);
|
||||
|
||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
||||
|
||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
var layers = printerDimensionsZ / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
var extruder = 0.0;
|
||||
var prev = new Point(); prev.set(0, 0);
|
||||
|
||||
|
@ -140,23 +72,32 @@ function generate_gcode(callback) {
|
|||
var centerOfDoodle = {
|
||||
x: doodleBounds[0] + (doodleBounds[2]- doodleBounds[0])/2,
|
||||
y: doodleBounds[1] + (doodleBounds[3] - doodleBounds[1])/2
|
||||
// x: doodleBounds[0],
|
||||
// y: doodleBounds[1]
|
||||
}
|
||||
|
||||
console.log("f:generategcode() >> layers: " + layers);
|
||||
if (layers == Infinity) return;
|
||||
|
||||
// check feasibility of design
|
||||
var pointsToPrint = points.length * layers*(objectHeight/printerDimensionsZ)
|
||||
|
||||
console.log("pointsToPrint: ",pointsToPrint);
|
||||
|
||||
if(pointsToPrint > MAX_POINTS_TO_PRINT) {
|
||||
alert("Sorry, your doodle is too complex or too high. Please try to simplify it.");
|
||||
console.log("ERROR: to many points too convert to gcode");
|
||||
return [];
|
||||
}
|
||||
|
||||
for (var layer = 0; layer < layers; layer++) {
|
||||
|
||||
//gcode.push(";LAYER:"+layer); //this will be added in a next release to support GCODE previewing in CURA
|
||||
|
||||
var p = JSON.parse(JSON.stringify(points)); // [].concat(points);
|
||||
|
||||
if (p.length < 2) return;
|
||||
var even = (layer % 2 == 0);
|
||||
var progress = layer / layers;
|
||||
|
||||
// float layerScale = scaleFunction(float(layer)/layers); // scaleFactor van de layer -> lookup naar vfunc[] voor die scaleVals
|
||||
// var layerScale = 1.0;
|
||||
var layerScale = scaleFunction(progress);
|
||||
|
||||
// if begin point this row and end point last row are close enough, isLoop is true
|
||||
|
@ -166,11 +107,6 @@ function generate_gcode(callback) {
|
|||
pointsTranslate(p, -centerOfDoodle.x, -centerOfDoodle.y);
|
||||
pointsScale(p, screenToMillimeterScale,-screenToMillimeterScale);
|
||||
pointsScale(p, layerScale, layerScale);
|
||||
|
||||
// sort-of in de buurt van (360/2.5)
|
||||
// // -> aight.. er zijn 750 lines vs 1000 in de d3d app. 135 = .75 * 180... dit kan je nog rechttrekken als je NET wat slimmer nadenkt :)
|
||||
// update: NEE, het is niet .75 * 180 want 135 was niet de beste value.
|
||||
//pointsRotate(p, rStep * progress * 139);
|
||||
pointsRotate(p, rStepGCode * layer);
|
||||
|
||||
if (layer == 0) {
|
||||
|
@ -204,24 +140,17 @@ function generate_gcode(callback) {
|
|||
paths[pathCounter].push([p[i][0], p[i][1]]);
|
||||
}
|
||||
}
|
||||
// console.log("f:generategcode() >> paths.length: " + paths.length);
|
||||
|
||||
// loop over the subpaths (the separately drawn lines)
|
||||
for (var j = 0; j < paths.length; j++) { // TODO paths > subpaths
|
||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
||||
// vector<ofSubPath::Command> &commands = subpaths[even ? j : subpaths.size()-1-j].getCommands();
|
||||
var commands = paths[j]; //commands zijn alle points uit subpath j // TODO commands > subpathPoints
|
||||
var commands = paths[j];
|
||||
|
||||
// loop over the coordinates of the subpath
|
||||
for (var i = 0; i < commands.length; i++) {
|
||||
var last = commands.length - 1;
|
||||
|
||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
||||
// ofPoint to = commands[(even || isLoop || loopAlways) ? i : last-i].to;
|
||||
var to = new Point(); to.set(commands[i][0], commands[i][1]);
|
||||
|
||||
// TODO 2013-09-18 evaluate if this should stay..
|
||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
||||
to.x += gCodeOffsetX;
|
||||
to.y += gCodeOffsetY;
|
||||
|
||||
|
@ -231,14 +160,16 @@ function generate_gcode(callback) {
|
|||
var isTraveling = !isLoop && i==0;
|
||||
var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance;
|
||||
|
||||
if (enableTraveling && isTraveling) {
|
||||
// console.log("enableTraveling && isTraveling >> doRetract: " + doRetract + ", retractionspeed: " + retractionspeed);
|
||||
if (doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract
|
||||
//Always travel to first point, then optionally disable traveling for first two layers and use settings for remainder of print.
|
||||
var firstPointEver = (layer == 0 && i == 0 && j == 0);
|
||||
var travelingAllowed = firstPointEver || bottomEnableTraveling || layer > 2;
|
||||
if (travelingAllowed && enableTraveling && isTraveling) {
|
||||
if (!firstPointEver && doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract
|
||||
gcode.push("G0 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (travelSpeed * 60).toFixed(3));
|
||||
if (doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
|
||||
if (!firstPointEver && doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
|
||||
} else {
|
||||
// console.log(" else");
|
||||
extruder += prev.distance(to) * wallThickness * layerHeight / filamentThickness;
|
||||
var f = (layer < 2) ? bottomFlowRate : 1;
|
||||
extruder += prev.distance(to) * wallThickness * layerHeight / (Math.pow((filamentThickness/2), 2) * Math.PI) * f;
|
||||
gcode.push("G1 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (speed * 60).toFixed(3) + " E" + extruder.toFixed(3));
|
||||
}
|
||||
|
||||
|
@ -250,26 +181,59 @@ function generate_gcode(callback) {
|
|||
|
||||
}
|
||||
|
||||
if ((layer/layers) > (objectHeight/maxObjectHeight)) {
|
||||
console.log("f:generategcode() >> (layer/layers) > (objectHeight/maxObjectHeight) is true -> breaking at layer " + (layer + 1));
|
||||
if ((layer/layers) > (objectHeight/printerDimensionsZ)) {
|
||||
console.log("f:generategcode() >> (layer/layers) > (objectHeight/printerDimensionsZ) is true -> breaking at layer " + (layer + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add gcode end commands
|
||||
gcode = gcode.concat(endGcode);
|
||||
gcode = gcode.concat(endCode);
|
||||
|
||||
// debug
|
||||
// var _gc = gc.join("\n");
|
||||
// console.log("f:generategcode() >> _gc = " + _gc);
|
||||
return gcode;
|
||||
}
|
||||
|
||||
// Return the gcode array, joined to one string with '\n' (line break) as the join parameter
|
||||
// This should result in a nice long string with line breaks
|
||||
if (callback == undefined) {
|
||||
return gcode;
|
||||
} else {
|
||||
// post
|
||||
function generateStartCode() {
|
||||
var printerType = settings["printer.type"];
|
||||
var startCode = settings["printer.startcode"];
|
||||
startCode = subsituteVariables(startCode);
|
||||
startCode = startCode.split("\n");
|
||||
return startCode;
|
||||
}
|
||||
function generateEndCode() {
|
||||
var printerType = settings["printer.type"];
|
||||
var endCode = settings["printer.endcode"];
|
||||
endCode = subsituteVariables(endCode);
|
||||
endCode = endCode.split("\n");
|
||||
return endCode;
|
||||
}
|
||||
|
||||
function subsituteVariables(gcode) {
|
||||
//,temperature,bedTemperature,preheatTemperature,preheatBedTemperature
|
||||
var temperature = settings["printer.temperature"];
|
||||
var bedTemperature = settings["printer.bed.temperature"];
|
||||
var preheatTemperature = settings["printer.heatup.temperature"];
|
||||
var preheatBedTemperature = settings["printer.heatup.bed.temperature"];
|
||||
var printerType = settings["printer.type"];
|
||||
var heatedbed = settings["printer.heatedbed"];
|
||||
|
||||
switch (printerType) {
|
||||
case "makerbot_replicator2": printerType = "r2"; break;
|
||||
case "makerbot_replicator2x": printerType = "r2x"; break;
|
||||
case "makerbot_thingomatic": printerType = "t6"; break;
|
||||
case "makerbot_generic": printerType = "r2"; break;
|
||||
case "wanhao_duplicator4": printerType = "r2x"; break;
|
||||
case "_3Dison_plus": printerType = "r2"; break;
|
||||
}
|
||||
var heatedBedReplacement = (heatedbed)? "" : ";";
|
||||
|
||||
gcode = gcode.replace(/{printingTemp}/gi ,temperature);
|
||||
gcode = gcode.replace(/{printingBedTemp}/gi ,bedTemperature);
|
||||
gcode = gcode.replace(/{preheatTemp}/gi ,preheatTemperature);
|
||||
gcode = gcode.replace(/{preheatBedTemp}/gi ,preheatBedTemperature);
|
||||
gcode = gcode.replace(/{printerType}/gi ,printerType);
|
||||
gcode = gcode.replace(/{if heatedBed}/gi ,heatedBedReplacement);
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
function scaleFunction(percent) {
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
// TODO refactor this stuff, there's much to wipe
|
||||
var drawAreaContainerMinHeight = 300;
|
||||
var drawAreaContainerMaxHeight = 450;
|
||||
|
||||
function doOnResize() {
|
||||
// console.log("doOnResize() >> " + new Date().getTime());
|
||||
// $(".container").css("height", window.innerHeight);
|
||||
|
||||
/* 2013-10-09 commented out -> no more need with new layouting
|
||||
$drawAreaContainer.css("marginLeft", -$drawAreaContainer.width()/2);
|
||||
$drawAreaContainer.css("marginTop", -$drawAreaContainer.height() *.45);
|
||||
// $drawAreaContainer.css("marginTop", -parseInt($drawAreaContainer.css("height")) * 0.45);
|
||||
//*/
|
||||
|
||||
// canvas.width = $drawAreaContainer.width() - preview.width; // canvas.clientWidth;
|
||||
// canvas.width = $("#mycanvasContainer").width();
|
||||
canvas.width = $canvas.width();
|
||||
canvas.height = $canvas.height(); // canvas.clientHeight;
|
||||
// canvas.height = $drawAreaContainer.height(); // canvas.clientHeight;
|
||||
|
||||
preview.width = $preview.width();
|
||||
preview.height = $drawAreaContainer.height();
|
||||
|
@ -24,84 +21,24 @@ function doOnResize() {
|
|||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
console.log(" preview.width: " + preview.width + ", $preview.width(): " + $preview.width());
|
||||
// console.log(" preview.width: " + preview.width + ", $preview.width(): " + $preview.width());
|
||||
|
||||
calcPreviewCanvasProperties();
|
||||
|
||||
// layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
// yStep = preview.height / 150;
|
||||
// preview.width = parseInt($preview.css("width"), 10);
|
||||
// preview.height = parseInt($preview.css("height"), 10);
|
||||
|
||||
// canvasWidth = canvas.width;
|
||||
// canvasHeight = canvas.height;
|
||||
|
||||
drawCanvasTopLeftCoords[0] = drawCanvas.offset().left;
|
||||
drawCanvasTopLeftCoords[1] = drawCanvas.offset().top;
|
||||
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
|
||||
|
||||
// preview.height = $("#previewContainer").height();
|
||||
// console.log("f:doOnResize() >> preview.height: " + preview.height);
|
||||
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
|
||||
return;
|
||||
|
||||
// doClientAndOrientationStuff() // <-- is this necessary in this method?
|
||||
|
||||
// console.log("f:doOnResize() >> $('#canvascontainer').innerHeight: " + window.innerHeight);
|
||||
if (window.innerHeight < 768) {
|
||||
// $('#drawAreaContainer').innerHeight(window.innerHeight - $("#drawAreaContainer").offset().top - 70);
|
||||
var newVal = window.innerHeight - $("#drawAreaContainer").offset().top - 100; // what's the 70 ??
|
||||
newVal = Math.max(newVal, drawAreaContainerMinHeight);
|
||||
newVal = Math.min(newVal, drawAreaContainerMaxHeight);
|
||||
|
||||
$('#drawAreaContainer').innerHeight(newVal);
|
||||
|
||||
// canvas drawing area
|
||||
$canvas.css("height", newVal);
|
||||
canvas.height = newVal;
|
||||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
// preview area
|
||||
$preview.css("height", newVal);
|
||||
preview.height = newVal;
|
||||
layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
yStep = preview.height / 150;
|
||||
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
}
|
||||
}
|
||||
|
||||
function initLayouting() {
|
||||
console.log("f:initLayouting()");
|
||||
//console.log("f:initLayouting()");
|
||||
|
||||
// first set the css width/height and actual width/height of the drawing area
|
||||
<!--div drawAreaContainer 650,450-->
|
||||
<!--canvas mycanvas 500, 450-->
|
||||
<!--canvas preview 150, 450-->
|
||||
$drawAreaContainer = $("#drawareacontainer");
|
||||
|
||||
// $doodleCanvas = $("#mycanvas");
|
||||
// doodleCanvas = $("#mycanvas")[0];
|
||||
// doodleCanvasContext = doodleCanvas.getContext('2d');
|
||||
|
||||
$drawAreaContainer = $(".drawareacontainer");
|
||||
/* 2013-10-09 commented out -> no more need with new layouting
|
||||
$drawAreaContainer.css("margin", 0);
|
||||
$drawAreaContainer.css("marginLeft", -$drawAreaContainer.width()/2);
|
||||
$drawAreaContainer.css("marginTop", -$drawAreaContainer.height() *.45);
|
||||
//*/
|
||||
|
||||
// console.log(" preview.width: " + preview.width + ", $preview.width(): " + $preview.width());
|
||||
// canvas.width = $drawAreaContainer.width() - preview.width; // canvas.clientWidth;
|
||||
// canvas.width = $("#mycanvasContainer").width();
|
||||
canvas.width = $canvas.width();
|
||||
canvas.height = $canvas.height(); // canvas.clientHeight;
|
||||
// canvas.height = $drawAreaContainer.height(); // canvas.clientHeight;
|
||||
|
||||
preview.width = $preview.width();
|
||||
preview.height = $drawAreaContainer.height();
|
||||
|
@ -112,17 +49,10 @@ function initLayouting() {
|
|||
$drawAreaContainer.show();
|
||||
|
||||
// window.innerHeight
|
||||
console.log("window.innerHeight: " + window.innerHeight);
|
||||
console.log("window.innerWidth: " + window.innerWidth);
|
||||
console.log("$drawAreaContainer.innerHeight(): " + $drawAreaContainer.innerHeight());
|
||||
console.log("$drawAreaContainer.offset().top: " + $drawAreaContainer.offset().top);
|
||||
|
||||
|
||||
/* 2013-07-26 not doing this resizing stuff now, it's not working well yet
|
||||
if (window.innerHeight < 768) {
|
||||
$('#drawAreaContainer').innerHeight(window.innerHeight - $("#drawAreaContainer").offset().top - 70);
|
||||
}
|
||||
//*/
|
||||
//console.log("window.innerHeight: " + window.innerHeight);
|
||||
//console.log("window.innerWidth: " + window.innerWidth);
|
||||
//console.log("$drawAreaContainer.innerHeight(): " + $drawAreaContainer.innerHeight());
|
||||
//console.log("$drawAreaContainer.offset().top: " + $drawAreaContainer.offset().top);
|
||||
|
||||
// timeout because it SEEMS to be beneficial for initting the layout
|
||||
// 2013-09-18 seems beneficial since when?
|
||||
|
@ -135,6 +65,5 @@ function _startOrientationAndChangeEventListening() {
|
|||
$(window).on('resize', doOnResize);
|
||||
|
||||
// is it necessary to call these? Aren't they called by the above eventhandlers?
|
||||
// doClientAndOrientationStuff();
|
||||
doOnResize();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
/* FileSaver.js
|
||||
* A saveAs() FileSaver implementation.
|
||||
* 2013-10-21
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* License: X11/MIT
|
||||
* See LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self */
|
||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||
plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||
|
||||
var saveAs = saveAs
|
||||
|| (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
|
||||
|| (function(view) {
|
||||
"use strict";
|
||||
var
|
||||
doc = view.document
|
||||
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
|
||||
, get_URL = function() {
|
||||
return view.URL || view.webkitURL || view;
|
||||
}
|
||||
, URL = view.URL || view.webkitURL || view
|
||||
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||
, can_use_save_link = !view.externalHost && "download" in save_link
|
||||
, click = function(node) {
|
||||
var event = doc.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click", true, false, view, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
);
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
, webkit_req_fs = view.webkitRequestFileSystem
|
||||
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
|
||||
, throw_outside = function (ex) {
|
||||
(view.setImmediate || view.setTimeout)(function() {
|
||||
throw ex;
|
||||
}, 0);
|
||||
}
|
||||
, force_saveable_type = "application/octet-stream"
|
||||
, fs_min_size = 0
|
||||
, deletion_queue = []
|
||||
, process_deletion_queue = function() {
|
||||
var i = deletion_queue.length;
|
||||
while (i--) {
|
||||
var file = deletion_queue[i];
|
||||
if (typeof file === "string") { // file is an object URL
|
||||
URL.revokeObjectURL(file);
|
||||
} else { // file is a File
|
||||
file.remove();
|
||||
}
|
||||
}
|
||||
deletion_queue.length = 0; // clear queue
|
||||
}
|
||||
, dispatch = function(filesaver, event_types, event) {
|
||||
event_types = [].concat(event_types);
|
||||
var i = event_types.length;
|
||||
while (i--) {
|
||||
var listener = filesaver["on" + event_types[i]];
|
||||
if (typeof listener === "function") {
|
||||
try {
|
||||
listener.call(filesaver, event || filesaver);
|
||||
} catch (ex) {
|
||||
throw_outside(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, FileSaver = function(blob, name) {
|
||||
// First try a.download, then web filesystem, then object URLs
|
||||
var
|
||||
filesaver = this
|
||||
, type = blob.type
|
||||
, blob_changed = false
|
||||
, object_url
|
||||
, target_view
|
||||
, get_object_url = function() {
|
||||
var object_url = get_URL().createObjectURL(blob);
|
||||
deletion_queue.push(object_url);
|
||||
return object_url;
|
||||
}
|
||||
, dispatch_all = function() {
|
||||
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||
}
|
||||
// on any filesys errors revert to saving with object URLs
|
||||
, fs_error = function() {
|
||||
// don't create more object URLs than needed
|
||||
if (blob_changed || !object_url) {
|
||||
object_url = get_object_url(blob);
|
||||
}
|
||||
if (target_view) {
|
||||
target_view.location.href = object_url;
|
||||
} else {
|
||||
window.open(object_url, "_blank");
|
||||
}
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
}
|
||||
, abortable = function(func) {
|
||||
return function() {
|
||||
if (filesaver.readyState !== filesaver.DONE) {
|
||||
return func.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
, create_if_not_found = {create: true, exclusive: false}
|
||||
, slice
|
||||
;
|
||||
filesaver.readyState = filesaver.INIT;
|
||||
if (!name) {
|
||||
name = "download";
|
||||
}
|
||||
if (can_use_save_link) {
|
||||
object_url = get_object_url(blob);
|
||||
// FF for Android has a nasty garbage collection mechanism
|
||||
// that turns all objects that are not pure javascript into 'deadObject'
|
||||
// this means `doc` and `save_link` are unusable and need to be recreated
|
||||
// `view` is usable though:
|
||||
doc = view.document;
|
||||
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
|
||||
save_link.href = object_url;
|
||||
save_link.download = name;
|
||||
var event = doc.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click", true, false, view, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
);
|
||||
save_link.dispatchEvent(event);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
return;
|
||||
}
|
||||
// Object and web filesystem URLs have a problem saving in Google Chrome when
|
||||
// viewed in a tab, so I force save with application/octet-stream
|
||||
// http://code.google.com/p/chromium/issues/detail?id=91158
|
||||
if (view.chrome && type && type !== force_saveable_type) {
|
||||
slice = blob.slice || blob.webkitSlice;
|
||||
blob = slice.call(blob, 0, blob.size, force_saveable_type);
|
||||
blob_changed = true;
|
||||
}
|
||||
// Since I can't be sure that the guessed media type will trigger a download
|
||||
// in WebKit, I append .download to the filename.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=65440
|
||||
if (webkit_req_fs && name !== "download") {
|
||||
name += ".download";
|
||||
}
|
||||
if (type === force_saveable_type || webkit_req_fs) {
|
||||
target_view = view;
|
||||
}
|
||||
if (!req_fs) {
|
||||
fs_error();
|
||||
return;
|
||||
}
|
||||
fs_min_size += blob.size;
|
||||
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
|
||||
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
|
||||
var save = function() {
|
||||
dir.getFile(name, create_if_not_found, abortable(function(file) {
|
||||
file.createWriter(abortable(function(writer) {
|
||||
writer.onwriteend = function(event) {
|
||||
target_view.location.href = file.toURL();
|
||||
deletion_queue.push(file);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "writeend", event);
|
||||
};
|
||||
writer.onerror = function() {
|
||||
var error = writer.error;
|
||||
if (error.code !== error.ABORT_ERR) {
|
||||
fs_error();
|
||||
}
|
||||
};
|
||||
"writestart progress write abort".split(" ").forEach(function(event) {
|
||||
writer["on" + event] = filesaver["on" + event];
|
||||
});
|
||||
writer.write(blob);
|
||||
filesaver.abort = function() {
|
||||
writer.abort();
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
};
|
||||
filesaver.readyState = filesaver.WRITING;
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
};
|
||||
dir.getFile(name, {create: false}, abortable(function(file) {
|
||||
// delete file if it already exists
|
||||
file.remove();
|
||||
save();
|
||||
}), abortable(function(ex) {
|
||||
if (ex.code === ex.NOT_FOUND_ERR) {
|
||||
save();
|
||||
} else {
|
||||
fs_error();
|
||||
}
|
||||
}));
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
}
|
||||
, FS_proto = FileSaver.prototype
|
||||
, saveAs = function(blob, name) {
|
||||
return new FileSaver(blob, name);
|
||||
}
|
||||
;
|
||||
FS_proto.abort = function() {
|
||||
var filesaver = this;
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "abort");
|
||||
};
|
||||
FS_proto.readyState = FS_proto.INIT = 0;
|
||||
FS_proto.WRITING = 1;
|
||||
FS_proto.DONE = 2;
|
||||
|
||||
FS_proto.error =
|
||||
FS_proto.onwritestart =
|
||||
FS_proto.onprogress =
|
||||
FS_proto.onwrite =
|
||||
FS_proto.onabort =
|
||||
FS_proto.onerror =
|
||||
FS_proto.onwriteend =
|
||||
null;
|
||||
|
||||
view.addEventListener("unload", process_deletion_queue, false);
|
||||
return saveAs;
|
||||
}(this.self || this.window || this.content));
|
||||
// `self` is undefined in Firefox for Android content script context
|
||||
// while `this` is nsIContentFrameMessageManager
|
||||
// with an attribute `content` that corresponds to the window
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = saveAs;
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2006 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
document.createElement("canvas").getContext||(function(){var s=Math,j=s.round,F=s.sin,G=s.cos,V=s.abs,W=s.sqrt,k=10,v=k/2;function X(){return this.context_||(this.context_=new H(this))}var L=Array.prototype.slice;function Y(b,a){var c=L.call(arguments,2);return function(){return b.apply(a,c.concat(L.call(arguments)))}}var M={init:function(b){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var a=b||document;a.createElement("canvas");a.attachEvent("onreadystatechange",Y(this.init_,this,a))}},init_:function(b){b.namespaces.g_vml_||
|
||||
b.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");b.namespaces.g_o_||b.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");if(!b.styleSheets.ex_canvas_){var a=b.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var c=b.getElementsByTagName("canvas"),d=0;for(;d<c.length;d++)this.initElement(c[d])},
|
||||
initElement:function(b){if(!b.getContext){b.getContext=X;b.innerHTML="";b.attachEvent("onpropertychange",Z);b.attachEvent("onresize",$);var a=b.attributes;if(a.width&&a.width.specified)b.style.width=a.width.nodeValue+"px";else b.width=b.clientWidth;if(a.height&&a.height.specified)b.style.height=a.height.nodeValue+"px";else b.height=b.clientHeight}return b}};function Z(b){var a=b.srcElement;switch(b.propertyName){case "width":a.style.width=a.attributes.width.nodeValue+"px";a.getContext().clearRect();
|
||||
break;case "height":a.style.height=a.attributes.height.nodeValue+"px";a.getContext().clearRect();break}}function $(b){var a=b.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+"px";a.firstChild.style.height=a.clientHeight+"px"}}M.init();var N=[],B=0;for(;B<16;B++){var C=0;for(;C<16;C++)N[B*16+C]=B.toString(16)+C.toString(16)}function I(){return[[1,0,0],[0,1,0],[0,0,1]]}function y(b,a){var c=I(),d=0;for(;d<3;d++){var f=0;for(;f<3;f++){var h=0,g=0;for(;g<3;g++)h+=b[d][g]*a[g][f];c[d][f]=
|
||||
h}}return c}function O(b,a){a.fillStyle=b.fillStyle;a.lineCap=b.lineCap;a.lineJoin=b.lineJoin;a.lineWidth=b.lineWidth;a.miterLimit=b.miterLimit;a.shadowBlur=b.shadowBlur;a.shadowColor=b.shadowColor;a.shadowOffsetX=b.shadowOffsetX;a.shadowOffsetY=b.shadowOffsetY;a.strokeStyle=b.strokeStyle;a.globalAlpha=b.globalAlpha;a.arcScaleX_=b.arcScaleX_;a.arcScaleY_=b.arcScaleY_;a.lineScale_=b.lineScale_}function P(b){var a,c=1;b=String(b);if(b.substring(0,3)=="rgb"){var d=b.indexOf("(",3),f=b.indexOf(")",d+
|
||||
1),h=b.substring(d+1,f).split(",");a="#";var g=0;for(;g<3;g++)a+=N[Number(h[g])];if(h.length==4&&b.substr(3,1)=="a")c=h[3]}else a=b;return{color:a,alpha:c}}function aa(b){switch(b){case "butt":return"flat";case "round":return"round";case "square":default:return"square"}}function H(b){this.m_=I();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=k*1;this.globalAlpha=1;this.canvas=b;
|
||||
var a=b.ownerDocument.createElement("div");a.style.width=b.clientWidth+"px";a.style.height=b.clientHeight+"px";a.style.overflow="hidden";a.style.position="absolute";b.appendChild(a);this.element_=a;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}var i=H.prototype;i.clearRect=function(){this.element_.innerHTML=""};i.beginPath=function(){this.currentPath_=[]};i.moveTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};
|
||||
i.lineTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};i.bezierCurveTo=function(b,a,c,d,f,h){var g=this.getCoords_(f,h),l=this.getCoords_(b,a),e=this.getCoords_(c,d);Q(this,l,e,g)};function Q(b,a,c,d){b.currentPath_.push({type:"bezierCurveTo",cp1x:a.x,cp1y:a.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y});b.currentX_=d.x;b.currentY_=d.y}i.quadraticCurveTo=function(b,a,c,d){var f=this.getCoords_(b,a),h=this.getCoords_(c,d),g={x:this.currentX_+
|
||||
0.6666666666666666*(f.x-this.currentX_),y:this.currentY_+0.6666666666666666*(f.y-this.currentY_)};Q(this,g,{x:g.x+(h.x-this.currentX_)/3,y:g.y+(h.y-this.currentY_)/3},h)};i.arc=function(b,a,c,d,f,h){c*=k;var g=h?"at":"wa",l=b+G(d)*c-v,e=a+F(d)*c-v,m=b+G(f)*c-v,r=a+F(f)*c-v;if(l==m&&!h)l+=0.125;var n=this.getCoords_(b,a),o=this.getCoords_(l,e),q=this.getCoords_(m,r);this.currentPath_.push({type:g,x:n.x,y:n.y,radius:c,xStart:o.x,yStart:o.y,xEnd:q.x,yEnd:q.y})};i.rect=function(b,a,c,d){this.moveTo(b,
|
||||
a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath()};i.strokeRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.stroke();this.currentPath_=f};i.fillRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.fill();this.currentPath_=f};i.createLinearGradient=function(b,
|
||||
a,c,d){var f=new D("gradient");f.x0_=b;f.y0_=a;f.x1_=c;f.y1_=d;return f};i.createRadialGradient=function(b,a,c,d,f,h){var g=new D("gradientradial");g.x0_=b;g.y0_=a;g.r0_=c;g.x1_=d;g.y1_=f;g.r1_=h;return g};i.drawImage=function(b){var a,c,d,f,h,g,l,e,m=b.runtimeStyle.width,r=b.runtimeStyle.height;b.runtimeStyle.width="auto";b.runtimeStyle.height="auto";var n=b.width,o=b.height;b.runtimeStyle.width=m;b.runtimeStyle.height=r;if(arguments.length==3){a=arguments[1];c=arguments[2];h=g=0;l=d=n;e=f=o}else if(arguments.length==
|
||||
5){a=arguments[1];c=arguments[2];d=arguments[3];f=arguments[4];h=g=0;l=n;e=o}else if(arguments.length==9){h=arguments[1];g=arguments[2];l=arguments[3];e=arguments[4];a=arguments[5];c=arguments[6];d=arguments[7];f=arguments[8]}else throw Error("Invalid number of arguments");var q=this.getCoords_(a,c),t=[];t.push(" <g_vml_:group",' coordsize="',k*10,",",k*10,'"',' coordorigin="0,0"',' style="width:',10,"px;height:",10,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]){var E=[];E.push("M11=",
|
||||
this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",j(q.x/k),",","Dy=",j(q.y/k),"");var p=q,z=this.getCoords_(a+d,c),w=this.getCoords_(a,c+f),x=this.getCoords_(a+d,c+f);p.x=s.max(p.x,z.x,w.x,x.x);p.y=s.max(p.y,z.y,w.y,x.y);t.push("padding:0 ",j(p.x/k),"px ",j(p.y/k),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",E.join(""),", sizingmethod='clip');")}else t.push("top:",j(q.y/k),"px;left:",j(q.x/k),"px;");t.push(' ">','<g_vml_:image src="',b.src,
|
||||
'"',' style="width:',k*d,"px;"," height:",k*f,'px;"',' cropleft="',h/n,'"',' croptop="',g/o,'"',' cropright="',(n-h-l)/n,'"',' cropbottom="',(o-g-e)/o,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",t.join(""))};i.stroke=function(b){var a=[],c=P(b?this.fillStyle:this.strokeStyle),d=c.color,f=c.alpha*this.globalAlpha;a.push("<g_vml_:shape",' filled="',!!b,'"',' style="position:absolute;width:',10,"px;height:",10,'px;"',' coordorigin="0 0" coordsize="',k*10," ",k*10,'"',' stroked="',
|
||||
!b,'"',' path="');var h={x:null,y:null},g={x:null,y:null},l=0;for(;l<this.currentPath_.length;l++){var e=this.currentPath_[l];switch(e.type){case "moveTo":a.push(" m ",j(e.x),",",j(e.y));break;case "lineTo":a.push(" l ",j(e.x),",",j(e.y));break;case "close":a.push(" x ");e=null;break;case "bezierCurveTo":a.push(" c ",j(e.cp1x),",",j(e.cp1y),",",j(e.cp2x),",",j(e.cp2y),",",j(e.x),",",j(e.y));break;case "at":case "wa":a.push(" ",e.type," ",j(e.x-this.arcScaleX_*e.radius),",",j(e.y-this.arcScaleY_*e.radius),
|
||||
" ",j(e.x+this.arcScaleX_*e.radius),",",j(e.y+this.arcScaleY_*e.radius)," ",j(e.xStart),",",j(e.yStart)," ",j(e.xEnd),",",j(e.yEnd));break}if(e){if(h.x==null||e.x<h.x)h.x=e.x;if(g.x==null||e.x>g.x)g.x=e.x;if(h.y==null||e.y<h.y)h.y=e.y;if(g.y==null||e.y>g.y)g.y=e.y}}a.push(' ">');if(b)if(typeof this.fillStyle=="object"){var m=this.fillStyle,r=0,n={x:0,y:0},o=0,q=1;if(m.type_=="gradient"){var t=m.x1_/this.arcScaleX_,E=m.y1_/this.arcScaleY_,p=this.getCoords_(m.x0_/this.arcScaleX_,m.y0_/this.arcScaleY_),
|
||||
z=this.getCoords_(t,E);r=Math.atan2(z.x-p.x,z.y-p.y)*180/Math.PI;if(r<0)r+=360;if(r<1.0E-6)r=0}else{var p=this.getCoords_(m.x0_,m.y0_),w=g.x-h.x,x=g.y-h.y;n={x:(p.x-h.x)/w,y:(p.y-h.y)/x};w/=this.arcScaleX_*k;x/=this.arcScaleY_*k;var R=s.max(w,x);o=2*m.r0_/R;q=2*m.r1_/R-o}var u=m.colors_;u.sort(function(ba,ca){return ba.offset-ca.offset});var J=u.length,da=u[0].color,ea=u[J-1].color,fa=u[0].alpha*this.globalAlpha,ga=u[J-1].alpha*this.globalAlpha,S=[],l=0;for(;l<J;l++){var T=u[l];S.push(T.offset*q+
|
||||
o+" "+T.color)}a.push('<g_vml_:fill type="',m.type_,'"',' method="none" focus="100%"',' color="',da,'"',' color2="',ea,'"',' colors="',S.join(","),'"',' opacity="',ga,'"',' g_o_:opacity2="',fa,'"',' angle="',r,'"',' focusposition="',n.x,",",n.y,'" />')}else a.push('<g_vml_:fill color="',d,'" opacity="',f,'" />');else{var K=this.lineScale_*this.lineWidth;if(K<1)f*=K;a.push("<g_vml_:stroke",' opacity="',f,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',aa(this.lineCap),
|
||||
'"',' weight="',K,'px"',' color="',d,'" />')}a.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",a.join(""))};i.fill=function(){this.stroke(true)};i.closePath=function(){this.currentPath_.push({type:"close"})};i.getCoords_=function(b,a){var c=this.m_;return{x:k*(b*c[0][0]+a*c[1][0]+c[2][0])-v,y:k*(b*c[0][1]+a*c[1][1]+c[2][1])-v}};i.save=function(){var b={};O(this,b);this.aStack_.push(b);this.mStack_.push(this.m_);this.m_=y(I(),this.m_)};i.restore=function(){O(this.aStack_.pop(),
|
||||
this);this.m_=this.mStack_.pop()};function ha(b){var a=0;for(;a<3;a++){var c=0;for(;c<2;c++)if(!isFinite(b[a][c])||isNaN(b[a][c]))return false}return true}function A(b,a,c){if(!!ha(a)){b.m_=a;if(c)b.lineScale_=W(V(a[0][0]*a[1][1]-a[0][1]*a[1][0]))}}i.translate=function(b,a){A(this,y([[1,0,0],[0,1,0],[b,a,1]],this.m_),false)};i.rotate=function(b){var a=G(b),c=F(b);A(this,y([[a,c,0],[-c,a,0],[0,0,1]],this.m_),false)};i.scale=function(b,a){this.arcScaleX_*=b;this.arcScaleY_*=a;A(this,y([[b,0,0],[0,a,
|
||||
0],[0,0,1]],this.m_),true)};i.transform=function(b,a,c,d,f,h){A(this,y([[b,a,0],[c,d,0],[f,h,1]],this.m_),true)};i.setTransform=function(b,a,c,d,f,h){A(this,[[b,a,0],[c,d,0],[f,h,1]],true)};i.clip=function(){};i.arcTo=function(){};i.createPattern=function(){return new U};function D(b){this.type_=b;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}D.prototype.addColorStop=function(b,a){a=P(a);this.colors_.push({offset:b,color:a.color,alpha:a.alpha})};function U(){}G_vmlCanvasManager=
|
||||
M;CanvasRenderingContext2D=H;CanvasGradient=D;CanvasPattern=U})();
|
|
@ -1,924 +0,0 @@
|
|||
// Copyright 2006 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
// Known Issues:
|
||||
//
|
||||
// * Patterns are not implemented.
|
||||
// * Radial gradient are not implemented. The VML version of these look very
|
||||
// different from the canvas one.
|
||||
// * Clipping paths are not implemented.
|
||||
// * Coordsize. The width and height attribute have higher priority than the
|
||||
// width and height style values which isn't correct.
|
||||
// * Painting mode isn't implemented.
|
||||
// * Canvas width/height should is using content-box by default. IE in
|
||||
// Quirks mode will draw the canvas using border-box. Either change your
|
||||
// doctype to HTML5
|
||||
// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
|
||||
// or use Box Sizing Behavior from WebFX
|
||||
// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
|
||||
// * Non uniform scaling does not correctly scale strokes.
|
||||
// * Optimize. There is always room for speed improvements.
|
||||
|
||||
// Only add this code if we do not already have a canvas implementation
|
||||
if (!document.createElement('canvas').getContext) {
|
||||
|
||||
(function() {
|
||||
|
||||
// alias some functions to make (compiled) code shorter
|
||||
var m = Math;
|
||||
var mr = m.round;
|
||||
var ms = m.sin;
|
||||
var mc = m.cos;
|
||||
var abs = m.abs;
|
||||
var sqrt = m.sqrt;
|
||||
|
||||
// this is used for sub pixel precision
|
||||
var Z = 10;
|
||||
var Z2 = Z / 2;
|
||||
|
||||
/**
|
||||
* This funtion is assigned to the <canvas> elements as element.getContext().
|
||||
* @this {HTMLElement}
|
||||
* @return {CanvasRenderingContext2D_}
|
||||
*/
|
||||
function getContext() {
|
||||
return this.context_ ||
|
||||
(this.context_ = new CanvasRenderingContext2D_(this));
|
||||
}
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
/**
|
||||
* Binds a function to an object. The returned function will always use the
|
||||
* passed in {@code obj} as {@code this}.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* g = bind(f, obj, a, b)
|
||||
* g(c, d) // will do f.call(obj, a, b, c, d)
|
||||
*
|
||||
* @param {Function} f The function to bind the object to
|
||||
* @param {Object} obj The object that should act as this when the function
|
||||
* is called
|
||||
* @param {*} var_args Rest arguments that will be used as the initial
|
||||
* arguments when the function is called
|
||||
* @return {Function} A new function that has bound this
|
||||
*/
|
||||
function bind(f, obj, var_args) {
|
||||
var a = slice.call(arguments, 2);
|
||||
return function() {
|
||||
return f.apply(obj, a.concat(slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
|
||||
var G_vmlCanvasManager_ = {
|
||||
init: function(opt_doc) {
|
||||
if (/MSIE/.test(navigator.userAgent) && !window.opera) {
|
||||
var doc = opt_doc || document;
|
||||
// Create a dummy element so that IE will allow canvas elements to be
|
||||
// recognized.
|
||||
doc.createElement('canvas');
|
||||
doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
|
||||
}
|
||||
},
|
||||
|
||||
init_: function(doc) {
|
||||
// create xmlns
|
||||
if (!doc.namespaces['g_vml_']) {
|
||||
doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
|
||||
'#default#VML');
|
||||
|
||||
}
|
||||
if (!doc.namespaces['g_o_']) {
|
||||
doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
|
||||
'#default#VML');
|
||||
}
|
||||
|
||||
// Setup default CSS. Only add one style sheet per document
|
||||
if (!doc.styleSheets['ex_canvas_']) {
|
||||
var ss = doc.createStyleSheet();
|
||||
ss.owningElement.id = 'ex_canvas_';
|
||||
ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
|
||||
// default size is 300x150 in Gecko and Opera
|
||||
'text-align:left;width:300px;height:150px}' +
|
||||
'g_vml_\\:*{behavior:url(#default#VML)}' +
|
||||
'g_o_\\:*{behavior:url(#default#VML)}';
|
||||
|
||||
}
|
||||
|
||||
// find all canvas elements
|
||||
var els = doc.getElementsByTagName('canvas');
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
this.initElement(els[i]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Public initializes a canvas element so that it can be used as canvas
|
||||
* element from now on. This is called automatically before the page is
|
||||
* loaded but if you are creating elements using createElement you need to
|
||||
* make sure this is called on the element.
|
||||
* @param {HTMLElement} el The canvas element to initialize.
|
||||
* @return {HTMLElement} the element that was created.
|
||||
*/
|
||||
initElement: function(el) {
|
||||
if (!el.getContext) {
|
||||
|
||||
el.getContext = getContext;
|
||||
|
||||
// Remove fallback content. There is no way to hide text nodes so we
|
||||
// just remove all childNodes. We could hide all elements and remove
|
||||
// text nodes but who really cares about the fallback content.
|
||||
el.innerHTML = '';
|
||||
|
||||
// do not use inline function because that will leak memory
|
||||
el.attachEvent('onpropertychange', onPropertyChange);
|
||||
el.attachEvent('onresize', onResize);
|
||||
|
||||
var attrs = el.attributes;
|
||||
if (attrs.width && attrs.width.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setWidth_(attrs.width.nodeValue);
|
||||
el.style.width = attrs.width.nodeValue + 'px';
|
||||
} else {
|
||||
el.width = el.clientWidth;
|
||||
}
|
||||
if (attrs.height && attrs.height.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setHeight_(attrs.height.nodeValue);
|
||||
el.style.height = attrs.height.nodeValue + 'px';
|
||||
} else {
|
||||
el.height = el.clientHeight;
|
||||
}
|
||||
//el.getContext().setCoordsize_()
|
||||
}
|
||||
return el;
|
||||
}
|
||||
};
|
||||
|
||||
function onPropertyChange(e) {
|
||||
var el = e.srcElement;
|
||||
|
||||
switch (e.propertyName) {
|
||||
case 'width':
|
||||
el.style.width = el.attributes.width.nodeValue + 'px';
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
case 'height':
|
||||
el.style.height = el.attributes.height.nodeValue + 'px';
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onResize(e) {
|
||||
var el = e.srcElement;
|
||||
if (el.firstChild) {
|
||||
el.firstChild.style.width = el.clientWidth + 'px';
|
||||
el.firstChild.style.height = el.clientHeight + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
G_vmlCanvasManager_.init();
|
||||
|
||||
// precompute "00" to "FF"
|
||||
var dec2hex = [];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
for (var j = 0; j < 16; j++) {
|
||||
dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
function createMatrixIdentity() {
|
||||
return [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
}
|
||||
|
||||
function matrixMultiply(m1, m2) {
|
||||
var result = createMatrixIdentity();
|
||||
|
||||
for (var x = 0; x < 3; x++) {
|
||||
for (var y = 0; y < 3; y++) {
|
||||
var sum = 0;
|
||||
|
||||
for (var z = 0; z < 3; z++) {
|
||||
sum += m1[x][z] * m2[z][y];
|
||||
}
|
||||
|
||||
result[x][y] = sum;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function copyState(o1, o2) {
|
||||
o2.fillStyle = o1.fillStyle;
|
||||
o2.lineCap = o1.lineCap;
|
||||
o2.lineJoin = o1.lineJoin;
|
||||
o2.lineWidth = o1.lineWidth;
|
||||
o2.miterLimit = o1.miterLimit;
|
||||
o2.shadowBlur = o1.shadowBlur;
|
||||
o2.shadowColor = o1.shadowColor;
|
||||
o2.shadowOffsetX = o1.shadowOffsetX;
|
||||
o2.shadowOffsetY = o1.shadowOffsetY;
|
||||
o2.strokeStyle = o1.strokeStyle;
|
||||
o2.globalAlpha = o1.globalAlpha;
|
||||
o2.arcScaleX_ = o1.arcScaleX_;
|
||||
o2.arcScaleY_ = o1.arcScaleY_;
|
||||
o2.lineScale_ = o1.lineScale_;
|
||||
}
|
||||
|
||||
function processStyle(styleString) {
|
||||
var str, alpha = 1;
|
||||
|
||||
styleString = String(styleString);
|
||||
if (styleString.substring(0, 3) == 'rgb') {
|
||||
var start = styleString.indexOf('(', 3);
|
||||
var end = styleString.indexOf(')', start + 1);
|
||||
var guts = styleString.substring(start + 1, end).split(',');
|
||||
|
||||
str = '#';
|
||||
for (var i = 0; i < 3; i++) {
|
||||
str += dec2hex[Number(guts[i])];
|
||||
}
|
||||
|
||||
if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
|
||||
alpha = guts[3];
|
||||
}
|
||||
} else {
|
||||
str = styleString;
|
||||
}
|
||||
|
||||
return {color: str, alpha: alpha};
|
||||
}
|
||||
|
||||
function processLineCap(lineCap) {
|
||||
switch (lineCap) {
|
||||
case 'butt':
|
||||
return 'flat';
|
||||
case 'round':
|
||||
return 'round';
|
||||
case 'square':
|
||||
default:
|
||||
return 'square';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements CanvasRenderingContext2D interface as described by
|
||||
* the WHATWG.
|
||||
* @param {HTMLElement} surfaceElement The element that the 2D context should
|
||||
* be associated with
|
||||
*/
|
||||
function CanvasRenderingContext2D_(surfaceElement) {
|
||||
this.m_ = createMatrixIdentity();
|
||||
|
||||
this.mStack_ = [];
|
||||
this.aStack_ = [];
|
||||
this.currentPath_ = [];
|
||||
|
||||
// Canvas context properties
|
||||
this.strokeStyle = '#000';
|
||||
this.fillStyle = '#000';
|
||||
|
||||
this.lineWidth = 1;
|
||||
this.lineJoin = 'miter';
|
||||
this.lineCap = 'butt';
|
||||
this.miterLimit = Z * 1;
|
||||
this.globalAlpha = 1;
|
||||
this.canvas = surfaceElement;
|
||||
|
||||
var el = surfaceElement.ownerDocument.createElement('div');
|
||||
el.style.width = surfaceElement.clientWidth + 'px';
|
||||
el.style.height = surfaceElement.clientHeight + 'px';
|
||||
el.style.overflow = 'hidden';
|
||||
el.style.position = 'absolute';
|
||||
surfaceElement.appendChild(el);
|
||||
|
||||
this.element_ = el;
|
||||
this.arcScaleX_ = 1;
|
||||
this.arcScaleY_ = 1;
|
||||
this.lineScale_ = 1;
|
||||
}
|
||||
|
||||
var contextPrototype = CanvasRenderingContext2D_.prototype;
|
||||
contextPrototype.clearRect = function() {
|
||||
this.element_.innerHTML = '';
|
||||
};
|
||||
|
||||
contextPrototype.beginPath = function() {
|
||||
// TODO: Branch current matrix so that save/restore has no effect
|
||||
// as per safari docs.
|
||||
this.currentPath_ = [];
|
||||
};
|
||||
|
||||
contextPrototype.moveTo = function(aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
|
||||
this.currentX_ = p.x;
|
||||
this.currentY_ = p.y;
|
||||
};
|
||||
|
||||
contextPrototype.lineTo = function(aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});
|
||||
|
||||
this.currentX_ = p.x;
|
||||
this.currentY_ = p.y;
|
||||
};
|
||||
|
||||
contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
|
||||
aCP2x, aCP2y,
|
||||
aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
var cp1 = this.getCoords_(aCP1x, aCP1y);
|
||||
var cp2 = this.getCoords_(aCP2x, aCP2y);
|
||||
bezierCurveTo(this, cp1, cp2, p);
|
||||
};
|
||||
|
||||
// Helper function that takes the already fixed cordinates.
|
||||
function bezierCurveTo(self, cp1, cp2, p) {
|
||||
self.currentPath_.push({
|
||||
type: 'bezierCurveTo',
|
||||
cp1x: cp1.x,
|
||||
cp1y: cp1.y,
|
||||
cp2x: cp2.x,
|
||||
cp2y: cp2.y,
|
||||
x: p.x,
|
||||
y: p.y
|
||||
});
|
||||
self.currentX_ = p.x;
|
||||
self.currentY_ = p.y;
|
||||
}
|
||||
|
||||
contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
|
||||
// the following is lifted almost directly from
|
||||
// http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
|
||||
|
||||
var cp = this.getCoords_(aCPx, aCPy);
|
||||
var p = this.getCoords_(aX, aY);
|
||||
|
||||
var cp1 = {
|
||||
x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
|
||||
y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
|
||||
};
|
||||
var cp2 = {
|
||||
x: cp1.x + (p.x - this.currentX_) / 3.0,
|
||||
y: cp1.y + (p.y - this.currentY_) / 3.0
|
||||
};
|
||||
|
||||
bezierCurveTo(this, cp1, cp2, p);
|
||||
};
|
||||
|
||||
contextPrototype.arc = function(aX, aY, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise) {
|
||||
aRadius *= Z;
|
||||
var arcType = aClockwise ? 'at' : 'wa';
|
||||
|
||||
var xStart = aX + mc(aStartAngle) * aRadius - Z2;
|
||||
var yStart = aY + ms(aStartAngle) * aRadius - Z2;
|
||||
|
||||
var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
|
||||
var yEnd = aY + ms(aEndAngle) * aRadius - Z2;
|
||||
|
||||
// IE won't render arches drawn counter clockwise if xStart == xEnd.
|
||||
if (xStart == xEnd && !aClockwise) {
|
||||
xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
|
||||
// that can be represented in binary
|
||||
}
|
||||
|
||||
var p = this.getCoords_(aX, aY);
|
||||
var pStart = this.getCoords_(xStart, yStart);
|
||||
var pEnd = this.getCoords_(xEnd, yEnd);
|
||||
|
||||
this.currentPath_.push({type: arcType,
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
radius: aRadius,
|
||||
xStart: pStart.x,
|
||||
yStart: pStart.y,
|
||||
xEnd: pEnd.x,
|
||||
yEnd: pEnd.y});
|
||||
|
||||
};
|
||||
|
||||
contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
};
|
||||
|
||||
contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
|
||||
var oldPath = this.currentPath_;
|
||||
this.beginPath();
|
||||
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.stroke();
|
||||
|
||||
this.currentPath_ = oldPath;
|
||||
};
|
||||
|
||||
contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
|
||||
var oldPath = this.currentPath_;
|
||||
this.beginPath();
|
||||
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.fill();
|
||||
|
||||
this.currentPath_ = oldPath;
|
||||
};
|
||||
|
||||
contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
|
||||
var gradient = new CanvasGradient_('gradient');
|
||||
gradient.x0_ = aX0;
|
||||
gradient.y0_ = aY0;
|
||||
gradient.x1_ = aX1;
|
||||
gradient.y1_ = aY1;
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
|
||||
aX1, aY1, aR1) {
|
||||
var gradient = new CanvasGradient_('gradientradial');
|
||||
gradient.x0_ = aX0;
|
||||
gradient.y0_ = aY0;
|
||||
gradient.r0_ = aR0;
|
||||
gradient.x1_ = aX1;
|
||||
gradient.y1_ = aY1;
|
||||
gradient.r1_ = aR1;
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.drawImage = function(image, var_args) {
|
||||
var dx, dy, dw, dh, sx, sy, sw, sh;
|
||||
|
||||
// to find the original width we overide the width and height
|
||||
var oldRuntimeWidth = image.runtimeStyle.width;
|
||||
var oldRuntimeHeight = image.runtimeStyle.height;
|
||||
image.runtimeStyle.width = 'auto';
|
||||
image.runtimeStyle.height = 'auto';
|
||||
|
||||
// get the original size
|
||||
var w = image.width;
|
||||
var h = image.height;
|
||||
|
||||
// and remove overides
|
||||
image.runtimeStyle.width = oldRuntimeWidth;
|
||||
image.runtimeStyle.height = oldRuntimeHeight;
|
||||
|
||||
if (arguments.length == 3) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
sx = sy = 0;
|
||||
sw = dw = w;
|
||||
sh = dh = h;
|
||||
} else if (arguments.length == 5) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
dw = arguments[3];
|
||||
dh = arguments[4];
|
||||
sx = sy = 0;
|
||||
sw = w;
|
||||
sh = h;
|
||||
} else if (arguments.length == 9) {
|
||||
sx = arguments[1];
|
||||
sy = arguments[2];
|
||||
sw = arguments[3];
|
||||
sh = arguments[4];
|
||||
dx = arguments[5];
|
||||
dy = arguments[6];
|
||||
dw = arguments[7];
|
||||
dh = arguments[8];
|
||||
} else {
|
||||
throw Error('Invalid number of arguments');
|
||||
}
|
||||
|
||||
var d = this.getCoords_(dx, dy);
|
||||
|
||||
var w2 = sw / 2;
|
||||
var h2 = sh / 2;
|
||||
|
||||
var vmlStr = [];
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
// For some reason that I've now forgotten, using divs didn't work
|
||||
vmlStr.push(' <g_vml_:group',
|
||||
' coordsize="', Z * W, ',', Z * H, '"',
|
||||
' coordorigin="0,0"' ,
|
||||
' style="width:', W, 'px;height:', H, 'px;position:absolute;');
|
||||
|
||||
// If filters are necessary (rotation exists), create them
|
||||
// filters are bog-slow, so only create them if abbsolutely necessary
|
||||
// The following check doesn't account for skews (which don't exist
|
||||
// in the canvas spec (yet) anyway.
|
||||
|
||||
if (this.m_[0][0] != 1 || this.m_[0][1]) {
|
||||
var filter = [];
|
||||
|
||||
// Note the 12/21 reversal
|
||||
filter.push('M11=', this.m_[0][0], ',',
|
||||
'M12=', this.m_[1][0], ',',
|
||||
'M21=', this.m_[0][1], ',',
|
||||
'M22=', this.m_[1][1], ',',
|
||||
'Dx=', mr(d.x / Z), ',',
|
||||
'Dy=', mr(d.y / Z), '');
|
||||
|
||||
// Bounding box calculation (need to minimize displayed area so that
|
||||
// filters don't waste time on unused pixels.
|
||||
var max = d;
|
||||
var c2 = this.getCoords_(dx + dw, dy);
|
||||
var c3 = this.getCoords_(dx, dy + dh);
|
||||
var c4 = this.getCoords_(dx + dw, dy + dh);
|
||||
|
||||
max.x = m.max(max.x, c2.x, c3.x, c4.x);
|
||||
max.y = m.max(max.y, c2.y, c3.y, c4.y);
|
||||
|
||||
vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
|
||||
'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
|
||||
filter.join(''), ", sizingmethod='clip');")
|
||||
} else {
|
||||
vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
|
||||
}
|
||||
|
||||
vmlStr.push(' ">' ,
|
||||
'<g_vml_:image src="', image.src, '"',
|
||||
' style="width:', Z * dw, 'px;',
|
||||
' height:', Z * dh, 'px;"',
|
||||
' cropleft="', sx / w, '"',
|
||||
' croptop="', sy / h, '"',
|
||||
' cropright="', (w - sx - sw) / w, '"',
|
||||
' cropbottom="', (h - sy - sh) / h, '"',
|
||||
' />',
|
||||
'</g_vml_:group>');
|
||||
|
||||
this.element_.insertAdjacentHTML('BeforeEnd',
|
||||
vmlStr.join(''));
|
||||
};
|
||||
|
||||
contextPrototype.stroke = function(aFill) {
|
||||
var lineStr = [];
|
||||
var lineOpen = false;
|
||||
var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
|
||||
var color = a.color;
|
||||
var opacity = a.alpha * this.globalAlpha;
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
lineStr.push('<g_vml_:shape',
|
||||
' filled="', !!aFill, '"',
|
||||
' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
|
||||
' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
|
||||
' stroked="', !aFill, '"',
|
||||
' path="');
|
||||
|
||||
var newSeq = false;
|
||||
var min = {x: null, y: null};
|
||||
var max = {x: null, y: null};
|
||||
|
||||
for (var i = 0; i < this.currentPath_.length; i++) {
|
||||
var p = this.currentPath_[i];
|
||||
var c;
|
||||
|
||||
switch (p.type) {
|
||||
case 'moveTo':
|
||||
c = p;
|
||||
lineStr.push(' m ', mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'lineTo':
|
||||
lineStr.push(' l ', mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'close':
|
||||
lineStr.push(' x ');
|
||||
p = null;
|
||||
break;
|
||||
case 'bezierCurveTo':
|
||||
lineStr.push(' c ',
|
||||
mr(p.cp1x), ',', mr(p.cp1y), ',',
|
||||
mr(p.cp2x), ',', mr(p.cp2y), ',',
|
||||
mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'at':
|
||||
case 'wa':
|
||||
lineStr.push(' ', p.type, ' ',
|
||||
mr(p.x - this.arcScaleX_ * p.radius), ',',
|
||||
mr(p.y - this.arcScaleY_ * p.radius), ' ',
|
||||
mr(p.x + this.arcScaleX_ * p.radius), ',',
|
||||
mr(p.y + this.arcScaleY_ * p.radius), ' ',
|
||||
mr(p.xStart), ',', mr(p.yStart), ' ',
|
||||
mr(p.xEnd), ',', mr(p.yEnd));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Following is broken for curves due to
|
||||
// move to proper paths.
|
||||
|
||||
// Figure out dimensions so we can do gradient fills
|
||||
// properly
|
||||
if (p) {
|
||||
if (min.x == null || p.x < min.x) {
|
||||
min.x = p.x;
|
||||
}
|
||||
if (max.x == null || p.x > max.x) {
|
||||
max.x = p.x;
|
||||
}
|
||||
if (min.y == null || p.y < min.y) {
|
||||
min.y = p.y;
|
||||
}
|
||||
if (max.y == null || p.y > max.y) {
|
||||
max.y = p.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineStr.push(' ">');
|
||||
|
||||
if (!aFill) {
|
||||
var lineWidth = this.lineScale_ * this.lineWidth;
|
||||
|
||||
// VML cannot correctly render a line if the width is less than 1px.
|
||||
// In that case, we dilute the color to make the line look thinner.
|
||||
if (lineWidth < 1) {
|
||||
opacity *= lineWidth;
|
||||
}
|
||||
|
||||
lineStr.push(
|
||||
'<g_vml_:stroke',
|
||||
' opacity="', opacity, '"',
|
||||
' joinstyle="', this.lineJoin, '"',
|
||||
' miterlimit="', this.miterLimit, '"',
|
||||
' endcap="', processLineCap(this.lineCap), '"',
|
||||
' weight="', lineWidth, 'px"',
|
||||
' color="', color, '" />'
|
||||
);
|
||||
} else if (typeof this.fillStyle == 'object') {
|
||||
var fillStyle = this.fillStyle;
|
||||
var angle = 0;
|
||||
var focus = {x: 0, y: 0};
|
||||
|
||||
// additional offset
|
||||
var shift = 0;
|
||||
// scale factor for offset
|
||||
var expansion = 1;
|
||||
|
||||
if (fillStyle.type_ == 'gradient') {
|
||||
var x0 = fillStyle.x0_ / this.arcScaleX_;
|
||||
var y0 = fillStyle.y0_ / this.arcScaleY_;
|
||||
var x1 = fillStyle.x1_ / this.arcScaleX_;
|
||||
var y1 = fillStyle.y1_ / this.arcScaleY_;
|
||||
var p0 = this.getCoords_(x0, y0);
|
||||
var p1 = this.getCoords_(x1, y1);
|
||||
var dx = p1.x - p0.x;
|
||||
var dy = p1.y - p0.y;
|
||||
angle = Math.atan2(dx, dy) * 180 / Math.PI;
|
||||
|
||||
// The angle should be a non-negative number.
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
|
||||
// Very small angles produce an unexpected result because they are
|
||||
// converted to a scientific notation string.
|
||||
if (angle < 1e-6) {
|
||||
angle = 0;
|
||||
}
|
||||
} else {
|
||||
var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
|
||||
var width = max.x - min.x;
|
||||
var height = max.y - min.y;
|
||||
focus = {
|
||||
x: (p0.x - min.x) / width,
|
||||
y: (p0.y - min.y) / height
|
||||
};
|
||||
|
||||
width /= this.arcScaleX_ * Z;
|
||||
height /= this.arcScaleY_ * Z;
|
||||
var dimension = m.max(width, height);
|
||||
shift = 2 * fillStyle.r0_ / dimension;
|
||||
expansion = 2 * fillStyle.r1_ / dimension - shift;
|
||||
}
|
||||
|
||||
// We need to sort the color stops in ascending order by offset,
|
||||
// otherwise IE won't interpret it correctly.
|
||||
var stops = fillStyle.colors_;
|
||||
stops.sort(function(cs1, cs2) {
|
||||
return cs1.offset - cs2.offset;
|
||||
});
|
||||
|
||||
var length = stops.length;
|
||||
var color1 = stops[0].color;
|
||||
var color2 = stops[length - 1].color;
|
||||
var opacity1 = stops[0].alpha * this.globalAlpha;
|
||||
var opacity2 = stops[length - 1].alpha * this.globalAlpha;
|
||||
|
||||
var colors = [];
|
||||
for (var i = 0; i < length; i++) {
|
||||
var stop = stops[i];
|
||||
colors.push(stop.offset * expansion + shift + ' ' + stop.color);
|
||||
}
|
||||
|
||||
// When colors attribute is used, the meanings of opacity and o:opacity2
|
||||
// are reversed.
|
||||
lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
|
||||
' method="none" focus="100%"',
|
||||
' color="', color1, '"',
|
||||
' color2="', color2, '"',
|
||||
' colors="', colors.join(','), '"',
|
||||
' opacity="', opacity2, '"',
|
||||
' g_o_:opacity2="', opacity1, '"',
|
||||
' angle="', angle, '"',
|
||||
' focusposition="', focus.x, ',', focus.y, '" />');
|
||||
} else {
|
||||
lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
|
||||
'" />');
|
||||
}
|
||||
|
||||
lineStr.push('</g_vml_:shape>');
|
||||
|
||||
this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
|
||||
};
|
||||
|
||||
contextPrototype.fill = function() {
|
||||
this.stroke(true);
|
||||
}
|
||||
|
||||
contextPrototype.closePath = function() {
|
||||
this.currentPath_.push({type: 'close'});
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
contextPrototype.getCoords_ = function(aX, aY) {
|
||||
var m = this.m_;
|
||||
return {
|
||||
x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
|
||||
y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
|
||||
}
|
||||
};
|
||||
|
||||
contextPrototype.save = function() {
|
||||
var o = {};
|
||||
copyState(this, o);
|
||||
this.aStack_.push(o);
|
||||
this.mStack_.push(this.m_);
|
||||
this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
|
||||
};
|
||||
|
||||
contextPrototype.restore = function() {
|
||||
copyState(this.aStack_.pop(), this);
|
||||
this.m_ = this.mStack_.pop();
|
||||
};
|
||||
|
||||
function matrixIsFinite(m) {
|
||||
for (var j = 0; j < 3; j++) {
|
||||
for (var k = 0; k < 2; k++) {
|
||||
if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function setM(ctx, m, updateLineScale) {
|
||||
if (!matrixIsFinite(m)) {
|
||||
return;
|
||||
}
|
||||
ctx.m_ = m;
|
||||
|
||||
if (updateLineScale) {
|
||||
// Get the line scale.
|
||||
// Determinant of this.m_ means how much the area is enlarged by the
|
||||
// transformation. So its square root can be used as a scale factor
|
||||
// for width.
|
||||
var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
|
||||
ctx.lineScale_ = sqrt(abs(det));
|
||||
}
|
||||
}
|
||||
|
||||
contextPrototype.translate = function(aX, aY) {
|
||||
var m1 = [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[aX, aY, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), false);
|
||||
};
|
||||
|
||||
contextPrototype.rotate = function(aRot) {
|
||||
var c = mc(aRot);
|
||||
var s = ms(aRot);
|
||||
|
||||
var m1 = [
|
||||
[c, s, 0],
|
||||
[-s, c, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), false);
|
||||
};
|
||||
|
||||
contextPrototype.scale = function(aX, aY) {
|
||||
this.arcScaleX_ *= aX;
|
||||
this.arcScaleY_ *= aY;
|
||||
var m1 = [
|
||||
[aX, 0, 0],
|
||||
[0, aY, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), true);
|
||||
};
|
||||
|
||||
contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
|
||||
var m1 = [
|
||||
[m11, m12, 0],
|
||||
[m21, m22, 0],
|
||||
[dx, dy, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), true);
|
||||
};
|
||||
|
||||
contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
|
||||
var m = [
|
||||
[m11, m12, 0],
|
||||
[m21, m22, 0],
|
||||
[dx, dy, 1]
|
||||
];
|
||||
|
||||
setM(this, m, true);
|
||||
};
|
||||
|
||||
/******** STUBS ********/
|
||||
contextPrototype.clip = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.arcTo = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.createPattern = function() {
|
||||
return new CanvasPattern_;
|
||||
};
|
||||
|
||||
// Gradient / Pattern Stubs
|
||||
function CanvasGradient_(aType) {
|
||||
this.type_ = aType;
|
||||
this.x0_ = 0;
|
||||
this.y0_ = 0;
|
||||
this.r0_ = 0;
|
||||
this.x1_ = 0;
|
||||
this.y1_ = 0;
|
||||
this.r1_ = 0;
|
||||
this.colors_ = [];
|
||||
}
|
||||
|
||||
CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
|
||||
aColor = processStyle(aColor);
|
||||
this.colors_.push({offset: aOffset,
|
||||
color: aColor.color,
|
||||
alpha: aColor.alpha});
|
||||
};
|
||||
|
||||
function CanvasPattern_() {}
|
||||
|
||||
// set up externs
|
||||
G_vmlCanvasManager = G_vmlCanvasManager_;
|
||||
CanvasRenderingContext2D = CanvasRenderingContext2D_;
|
||||
CanvasGradient = CanvasGradient_;
|
||||
CanvasPattern = CanvasPattern_;
|
||||
|
||||
})();
|
||||
|
||||
} // if
|
|
@ -1,499 +0,0 @@
|
|||
/**
|
||||
* @preserve HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.6.2';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/\w+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
/*------------------------------- Print Shiv -------------------------------*/
|
||||
|
||||
/** Used to filter media types */
|
||||
var reMedia = /^$|\b(?:all|print)\b/;
|
||||
|
||||
/** Used to namespace printable elements */
|
||||
var shivNamespace = 'html5shiv';
|
||||
|
||||
/** Detect whether the browser supports shivable style sheets */
|
||||
var supportsShivableSheets = !supportsUnknownElements && (function() {
|
||||
// assign a false negative if unable to shiv
|
||||
var docEl = document.documentElement;
|
||||
return !(
|
||||
typeof document.namespaces == 'undefined' ||
|
||||
typeof document.parentWindow == 'undefined' ||
|
||||
typeof docEl.applyElement == 'undefined' ||
|
||||
typeof docEl.removeNode == 'undefined' ||
|
||||
typeof window.attachEvent == 'undefined'
|
||||
);
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Wraps all HTML5 elements in the given document with printable elements.
|
||||
* (eg. the "header" element is wrapped with the "html5shiv:header" element)
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Array} An array wrappers added.
|
||||
*/
|
||||
function addWrappers(ownerDocument) {
|
||||
var node,
|
||||
nodes = ownerDocument.getElementsByTagName('*'),
|
||||
index = nodes.length,
|
||||
reElements = RegExp('^(?:' + getElements().join('|') + ')$', 'i'),
|
||||
result = [];
|
||||
|
||||
while (index--) {
|
||||
node = nodes[index];
|
||||
if (reElements.test(node.nodeName)) {
|
||||
result.push(node.applyElement(createWrapper(node)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a printable wrapper for the given element.
|
||||
* @private
|
||||
* @param {Element} element The element.
|
||||
* @returns {Element} The wrapper.
|
||||
*/
|
||||
function createWrapper(element) {
|
||||
var node,
|
||||
nodes = element.attributes,
|
||||
index = nodes.length,
|
||||
wrapper = element.ownerDocument.createElement(shivNamespace + ':' + element.nodeName);
|
||||
|
||||
// copy element attributes to the wrapper
|
||||
while (index--) {
|
||||
node = nodes[index];
|
||||
node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue);
|
||||
}
|
||||
// copy element styles to the wrapper
|
||||
wrapper.style.cssText = element.style.cssText;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the given CSS text.
|
||||
* (eg. header{} becomes html5shiv\:header{})
|
||||
* @private
|
||||
* @param {String} cssText The CSS text to shiv.
|
||||
* @returns {String} The shived CSS text.
|
||||
*/
|
||||
function shivCssText(cssText) {
|
||||
var pair,
|
||||
parts = cssText.split('{'),
|
||||
index = parts.length,
|
||||
reElements = RegExp('(^|[\\s,>+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'),
|
||||
replacement = '$1' + shivNamespace + '\\:$2';
|
||||
|
||||
while (index--) {
|
||||
pair = parts[index] = parts[index].split('}');
|
||||
pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);
|
||||
parts[index] = pair.join('}');
|
||||
}
|
||||
return parts.join('{');
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given wrappers, leaving the original elements.
|
||||
* @private
|
||||
* @params {Array} wrappers An array of printable wrappers.
|
||||
*/
|
||||
function removeWrappers(wrappers) {
|
||||
var index = wrappers.length;
|
||||
while (index--) {
|
||||
wrappers[index].removeNode();
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document for print.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivPrint(ownerDocument) {
|
||||
var shivedSheet,
|
||||
wrappers,
|
||||
data = getExpandoData(ownerDocument),
|
||||
namespaces = ownerDocument.namespaces,
|
||||
ownerWindow = ownerDocument.parentWindow;
|
||||
|
||||
if (!supportsShivableSheets || ownerDocument.printShived) {
|
||||
return ownerDocument;
|
||||
}
|
||||
if (typeof namespaces[shivNamespace] == 'undefined') {
|
||||
namespaces.add(shivNamespace);
|
||||
}
|
||||
|
||||
function removeSheet() {
|
||||
clearTimeout(data._removeSheetTimer);
|
||||
if (shivedSheet) {
|
||||
shivedSheet.removeNode(true);
|
||||
}
|
||||
shivedSheet= null;
|
||||
}
|
||||
|
||||
ownerWindow.attachEvent('onbeforeprint', function() {
|
||||
|
||||
removeSheet();
|
||||
|
||||
var imports,
|
||||
length,
|
||||
sheet,
|
||||
collection = ownerDocument.styleSheets,
|
||||
cssText = [],
|
||||
index = collection.length,
|
||||
sheets = Array(index);
|
||||
|
||||
// convert styleSheets collection to an array
|
||||
while (index--) {
|
||||
sheets[index] = collection[index];
|
||||
}
|
||||
// concat all style sheet CSS text
|
||||
while ((sheet = sheets.pop())) {
|
||||
// IE does not enforce a same origin policy for external style sheets...
|
||||
// but has trouble with some dynamically created stylesheets
|
||||
if (!sheet.disabled && reMedia.test(sheet.media)) {
|
||||
|
||||
try {
|
||||
imports = sheet.imports;
|
||||
length = imports.length;
|
||||
} catch(er){
|
||||
length = 0;
|
||||
}
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
sheets.push(imports[index]);
|
||||
}
|
||||
|
||||
try {
|
||||
cssText.push(sheet.cssText);
|
||||
} catch(er){}
|
||||
}
|
||||
}
|
||||
|
||||
// wrap all HTML5 elements with printable elements and add the shived style sheet
|
||||
cssText = shivCssText(cssText.reverse().join(''));
|
||||
wrappers = addWrappers(ownerDocument);
|
||||
shivedSheet = addStyleSheet(ownerDocument, cssText);
|
||||
|
||||
});
|
||||
|
||||
ownerWindow.attachEvent('onafterprint', function() {
|
||||
// remove wrappers, leaving the original elements, and remove the shived style sheet
|
||||
removeWrappers(wrappers);
|
||||
clearTimeout(data._removeSheetTimer);
|
||||
data._removeSheetTimer = setTimeout(removeSheet, 500);
|
||||
});
|
||||
|
||||
ownerDocument.printShived = true;
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose API
|
||||
html5.type += ' print';
|
||||
html5.shivPrint = shivPrint;
|
||||
|
||||
// shiv for print
|
||||
shivPrint(document);
|
||||
|
||||
}(this, document));
|
|
@ -1,301 +0,0 @@
|
|||
/**
|
||||
* @preserve HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.6.2';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/\w+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
}(this, document));
|
|
@ -0,0 +1,72 @@
|
|||
/*jshint eqnull:true */
|
||||
/*!
|
||||
* jQuery Cookie Plugin v1.2
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2011, Klaus Hartl
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.opensource.org/licenses/GPL-2.0
|
||||
*/
|
||||
(function ($, document, undefined) {
|
||||
|
||||
var pluses = /\+/g;
|
||||
|
||||
function raw(s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
function decoded(s) {
|
||||
return decodeURIComponent(s.replace(pluses, ' '));
|
||||
}
|
||||
|
||||
$.cookie = function (key, value, options) {
|
||||
|
||||
// key and at least value given, set cookie...
|
||||
if (value !== undefined && !/Object/.test(Object.prototype.toString.call(value))) {
|
||||
options = $.extend({}, $.cookie.defaults, options);
|
||||
|
||||
if (value === null) {
|
||||
options.expires = -1;
|
||||
}
|
||||
|
||||
if (typeof options.expires === 'number') {
|
||||
var days = options.expires, t = options.expires = new Date();
|
||||
t.setDate(t.getDate() + days);
|
||||
}
|
||||
|
||||
value = String(value);
|
||||
|
||||
return (document.cookie = [
|
||||
encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
|
||||
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||
options.path ? '; path=' + options.path : '',
|
||||
options.domain ? '; domain=' + options.domain : '',
|
||||
options.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// key and possibly options given, get cookie...
|
||||
options = value || $.cookie.defaults || {};
|
||||
var decode = options.raw ? raw : decoded;
|
||||
var cookies = document.cookie.split('; ');
|
||||
for (var i = 0, parts; (parts = cookies[i] && cookies[i].split('=')); i++) {
|
||||
if (decode(parts.shift()) === key) {
|
||||
return decode(parts.join('='));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
$.cookie.defaults = {};
|
||||
|
||||
$.removeCookie = function (key, options) {
|
||||
if ($.cookie(key, options) !== null) {
|
||||
$.cookie(key, null, options);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
})(jQuery, document);
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* jQuery Plugin for creating collapsible fieldset
|
||||
* @requires jQuery 1.2 or later
|
||||
*
|
||||
* Copyright (c) 2010 Lucky <bogeyman2007@gmail.com>
|
||||
* Licensed under the GPL license:
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* "animation" and "speed" options are added by Mitch Kuppinger <dpneumo@gmail.com>
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
function hideFieldsetContent(obj, options){
|
||||
if(options.animation==true)
|
||||
obj.find('div').slideUp(options.speed);
|
||||
else
|
||||
obj.find('div').hide();
|
||||
|
||||
obj.removeClass("expanded");
|
||||
obj.addClass("collapsed");
|
||||
}
|
||||
|
||||
function showFieldsetContent(obj, options){
|
||||
if(options.animation==true)
|
||||
obj.find('div').slideDown(options.speed);
|
||||
else
|
||||
obj.find('div').show();
|
||||
|
||||
obj.removeClass("collapsed");
|
||||
obj.addClass("expanded");
|
||||
}
|
||||
|
||||
$.fn.coolfieldset = function(options){
|
||||
var setting={collapsed:false, animation:true, speed:'medium'};
|
||||
$.extend(setting, options);
|
||||
|
||||
this.each(function(){
|
||||
var fieldset=$(this);
|
||||
fieldset.addClass("collapsible");
|
||||
var legend=fieldset.children('legend');
|
||||
|
||||
if(setting.collapsed==true){
|
||||
hideFieldsetContent(fieldset, setting);
|
||||
} else {
|
||||
showFieldsetContent(fieldset, setting);
|
||||
}
|
||||
|
||||
// legend.bind('touchstart mousedown', function() {
|
||||
legend.bind('click', function() {
|
||||
if(fieldset.hasClass("collapsed")) {
|
||||
showFieldsetContent(fieldset, setting);
|
||||
} else {
|
||||
hideFieldsetContent(fieldset, setting);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* jQuery.fastClick.js
|
||||
*
|
||||
* Work around the 300ms delay for the click event in some mobile browsers.
|
||||
*
|
||||
* Code based on <http://code.google.com/mobile/articles/fast_buttons.html>
|
||||
*
|
||||
* @usage
|
||||
* $('button').fastClick(function() {alert('clicked!');});
|
||||
*
|
||||
* @license MIT
|
||||
* @author Dave Hulbert (dave1010)
|
||||
* @version 1.0.0 2013-01-17
|
||||
*/
|
||||
|
||||
/*global document, window, jQuery, Math */
|
||||
|
||||
(function($) {
|
||||
|
||||
$.fn.fastClick = function(handler) {
|
||||
return $(this).each(function(){
|
||||
$.FastButton($(this)[0], handler);
|
||||
});
|
||||
};
|
||||
|
||||
$.FastButton = function(element, handler) {
|
||||
var startX, startY;
|
||||
|
||||
var reset = function() {
|
||||
$(element).unbind('touchend');
|
||||
$("body").unbind('touchmove.fastClick');
|
||||
};
|
||||
|
||||
var onClick = function(event) {
|
||||
event.stopPropagation();
|
||||
reset();
|
||||
handler.call(this, event);
|
||||
|
||||
if (event.type === 'touchend') {
|
||||
$.clickbuster.preventGhostClick(startX, startY);
|
||||
}
|
||||
};
|
||||
|
||||
var onTouchMove = function(event) {
|
||||
if (Math.abs(event.originalEvent.touches[0].clientX - startX) > 10 ||
|
||||
Math.abs(event.originalEvent.touches[0].clientY - startY) > 10) {
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
var onTouchStart = function(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
$(element).bind('touchend', onClick);
|
||||
$("body").bind('touchmove.fastClick', onTouchMove);
|
||||
|
||||
startX = event.originalEvent.touches[0].clientX;
|
||||
startY = event.originalEvent.touches[0].clientY;
|
||||
};
|
||||
|
||||
$(element).bind({
|
||||
touchstart: onTouchStart,
|
||||
click: onClick
|
||||
});
|
||||
};
|
||||
|
||||
$.clickbuster = {
|
||||
coordinates: [],
|
||||
|
||||
preventGhostClick: function(x, y) {
|
||||
$.clickbuster.coordinates.push(x, y);
|
||||
window.setTimeout($.clickbuster.pop, 2500);
|
||||
},
|
||||
|
||||
pop: function() {
|
||||
$.clickbuster.coordinates.splice(0, 2);
|
||||
},
|
||||
|
||||
onClick: function(event) {
|
||||
var x, y, i;
|
||||
for (i = 0; i < $.clickbuster.coordinates.length; i += 2) {
|
||||
x = $.clickbuster.coordinates[i];
|
||||
y = $.clickbuster.coordinates[i + 1];
|
||||
if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$(function(){
|
||||
if (document.addEventListener){
|
||||
document.addEventListener('click', $.clickbuster.onClick, true);
|
||||
} else if (document.attachEvent){
|
||||
// for IE 7/8
|
||||
document.attachEvent('onclick', $.clickbuster.onClick);
|
||||
}
|
||||
});
|
||||
|
||||
}(jQuery));
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* jQuery Foundation Joyride Plugin 2.1
|
||||
* http://foundation.zurb.com
|
||||
* Copyright 2013, ZURB
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/*jslint unparam: true, browser: true, indent: 2 */
|
||||
|
||||
;(function ($, window, undefined) {
|
||||
'use strict';
|
||||
|
||||
var defaults = {
|
||||
'version' : '2.1',
|
||||
'tipLocation' : 'bottom', // 'top' or 'bottom' in relation to parent
|
||||
'nubPosition' : 'auto', // override on a per tooltip bases
|
||||
'scroll' : true, // whether to scroll to tips
|
||||
'scrollSpeed' : 300, // Page scrolling speed in milliseconds
|
||||
'timer' : 0, // 0 = no timer , all other numbers = timer in milliseconds
|
||||
'autoStart' : false, // true or false - false tour starts when restart called
|
||||
'startTimerOnClick' : true, // true or false - true requires clicking the first button start the timer
|
||||
'startOffset' : 0, // the index of the tooltip you want to start on (index of the li)
|
||||
'nextButton' : true, // true or false to control whether a next button is used
|
||||
'tipAnimation' : 'fade', // 'pop' or 'fade' in each tip
|
||||
'pauseAfter' : [], // array of indexes where to pause the tour after
|
||||
'tipAnimationFadeSpeed': 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition
|
||||
'cookieMonster' : false, // true or false to control whether cookies are used
|
||||
'cookieName' : 'joyride', // Name the cookie you'll use
|
||||
'cookieDomain' : false, // Will this cookie be attached to a domain, ie. '.notableapp.com'
|
||||
'cookiePath' : false, // Set to '/' if you want the cookie for the whole website
|
||||
'localStorage' : false, // true or false to control whether localstorage is used
|
||||
'localStorageKey' : 'joyride', // Keyname in localstorage
|
||||
'tipContainer' : 'body', // Where will the tip be attached
|
||||
'modal' : false, // Whether to cover page with modal during the tour
|
||||
'expose' : false, // Whether to expose the elements at each step in the tour (requires modal:true)
|
||||
'postExposeCallback' : $.noop, // A method to call after an element has been exposed
|
||||
'preRideCallback' : $.noop, // A method to call before the tour starts (passed index, tip, and cloned exposed element)
|
||||
'postRideCallback' : $.noop, // A method to call once the tour closes (canceled or complete)
|
||||
'preStepCallback' : $.noop, // A method to call before each step
|
||||
'postStepCallback' : $.noop, // A method to call after each step
|
||||
'template' : { // HTML segments for tip layout
|
||||
'link' : '<a href="#close" class="joyride-close-tip">X</a>',
|
||||
'timer' : '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
|
||||
'tip' : '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
|
||||
'wrapper' : '<div class="joyride-content-wrapper" role="dialog"></div>',
|
||||
'button' : '<a href="#" class="joyride-next-tip"></a>',
|
||||
'modal' : '<div class="joyride-modal-bg"></div>',
|
||||
'expose' : '<div class="joyride-expose-wrapper"></div>',
|
||||
'exposeCover': '<div class="joyride-expose-cover"></div>'
|
||||
}
|
||||
},
|
||||
|
||||
Modernizr = Modernizr || false,
|
||||
|
||||
settings = {},
|
||||
|
||||
methods = {
|
||||
|
||||
init : function (opts) {
|
||||
return this.each(function () {
|
||||
|
||||
if ($.isEmptyObject(settings)) {
|
||||
settings = $.extend(true, defaults, opts);
|
||||
|
||||
// non configurable settings
|
||||
settings.document = window.document;
|
||||
settings.$document = $(settings.document);
|
||||
settings.$window = $(window);
|
||||
settings.$content_el = $(this);
|
||||
settings.$body = $(settings.tipContainer);
|
||||
settings.body_offset = $(settings.tipContainer).position();
|
||||
settings.$tip_content = $('> li', settings.$content_el);
|
||||
settings.paused = false;
|
||||
settings.attempts = 0;
|
||||
|
||||
settings.tipLocationPatterns = {
|
||||
top: ['bottom'],
|
||||
bottom: [], // bottom should not need to be repositioned
|
||||
left: ['right', 'top', 'bottom'],
|
||||
right: ['left', 'top', 'bottom']
|
||||
};
|
||||
|
||||
// are we using jQuery 1.7+
|
||||
methods.jquery_check();
|
||||
|
||||
// can we create cookies?
|
||||
if (!$.isFunction($.cookie)) {
|
||||
settings.cookieMonster = false;
|
||||
}
|
||||
|
||||
// generate the tips and insert into dom.
|
||||
if ( (!settings.cookieMonster || !$.cookie(settings.cookieName) ) &&
|
||||
(!settings.localStorage || !methods.support_localstorage() || !localStorage.getItem(settings.localStorageKey) ) ) {
|
||||
|
||||
settings.$tip_content.each(function (index) {
|
||||
methods.create({$li : $(this), index : index});
|
||||
});
|
||||
|
||||
// show first tip
|
||||
if(settings.autoStart)
|
||||
{
|
||||
if (!settings.startTimerOnClick && settings.timer > 0) {
|
||||
methods.show('init');
|
||||
methods.startTimer();
|
||||
} else {
|
||||
methods.show('init');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
settings.$document.on('click.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (settings.$li.next().length < 1) {
|
||||
methods.end();
|
||||
} else if (settings.timer > 0) {
|
||||
clearTimeout(settings.automate);
|
||||
methods.hide();
|
||||
methods.show();
|
||||
methods.startTimer();
|
||||
} else {
|
||||
methods.hide();
|
||||
methods.show();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
settings.$document.on('click.joyride', '.joyride-close-tip', function (e) {
|
||||
e.preventDefault();
|
||||
methods.end();
|
||||
});
|
||||
|
||||
settings.$window.bind('resize.joyride', function (e) {
|
||||
if(settings.$li){
|
||||
if(settings.exposed && settings.exposed.length>0){
|
||||
var $els = $(settings.exposed);
|
||||
$els.each(function(){
|
||||
var $this = $(this);
|
||||
methods.un_expose($this);
|
||||
methods.expose($this);
|
||||
});
|
||||
}
|
||||
if (methods.is_phone()) {
|
||||
methods.pos_phone();
|
||||
} else {
|
||||
methods.pos_default();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
methods.restart();
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
// call this method when you want to resume the tour
|
||||
resume : function () {
|
||||
methods.set_li();
|
||||
methods.show();
|
||||
},
|
||||
|
||||
nextTip: function(){
|
||||
if (settings.$li.next().length < 1) {
|
||||
methods.end();
|
||||
} else if (settings.timer > 0) {
|
||||
clearTimeout(settings.automate);
|
||||
methods.hide();
|
||||
methods.show();
|
||||
methods.startTimer();
|
||||
} else {
|
||||
methods.hide();
|
||||
methods.show();
|
||||
}
|
||||
},
|
||||
|
||||
tip_template : function (opts) {
|
||||
var $blank, content, $wrapper;
|
||||
|
||||
opts.tip_class = opts.tip_class || '';
|
||||
|
||||
$blank = $(settings.template.tip).addClass(opts.tip_class);
|
||||
content = $.trim($(opts.li).html()) +
|
||||
methods.button_text(opts.button_text) +
|
||||
settings.template.link +
|
||||
methods.timer_instance(opts.index);
|
||||
|
||||
$wrapper = $(settings.template.wrapper);
|
||||
if (opts.li.attr('data-aria-labelledby')) {
|
||||
$wrapper.attr('aria-labelledby', opts.li.attr('data-aria-labelledby'))
|
||||
}
|
||||
if (opts.li.attr('data-aria-describedby')) {
|
||||
$wrapper.attr('aria-describedby', opts.li.attr('data-aria-describedby'))
|
||||
}
|
||||
$blank.append($wrapper);
|
||||
$blank.first().attr('data-index', opts.index);
|
||||
$('.joyride-content-wrapper', $blank).append(content);
|
||||
|
||||
return $blank[0];
|
||||
},
|
||||
|
||||
timer_instance : function (index) {
|
||||
var txt;
|
||||
|
||||
if ((index === 0 && settings.startTimerOnClick && settings.timer > 0) || settings.timer === 0) {
|
||||
txt = '';
|
||||
} else {
|
||||
txt = methods.outerHTML($(settings.template.timer)[0]);
|
||||
}
|
||||
return txt;
|
||||
},
|
||||
|
||||
button_text : function (txt) {
|
||||
if (settings.nextButton) {
|
||||
txt = $.trim(txt) || 'Next';
|
||||
txt = methods.outerHTML($(settings.template.button).append(txt)[0]);
|
||||
} else {
|
||||
txt = '';
|
||||
}
|
||||
return txt;
|
||||
},
|
||||
|
||||
create : function (opts) {
|
||||
// backwards compatibility with data-text attribute
|
||||
var buttonText = opts.$li.attr('data-button') || opts.$li.attr('data-text'),
|
||||
tipClass = opts.$li.attr('class'),
|
||||
$tip_content = $(methods.tip_template({
|
||||
tip_class : tipClass,
|
||||
index : opts.index,
|
||||
button_text : buttonText,
|
||||
li : opts.$li
|
||||
}));
|
||||
|
||||
$(settings.tipContainer).append($tip_content);
|
||||
},
|
||||
|
||||
show : function (init) {
|
||||
var opts = {}, ii, opts_arr = [], opts_len = 0, p,
|
||||
$timer = null;
|
||||
|
||||
// are we paused?
|
||||
if (settings.$li === undefined || ($.inArray(settings.$li.index(), settings.pauseAfter) === -1)) {
|
||||
|
||||
// don't go to the next li if the tour was paused
|
||||
if (settings.paused) {
|
||||
settings.paused = false;
|
||||
} else {
|
||||
methods.set_li(init);
|
||||
}
|
||||
|
||||
settings.attempts = 0;
|
||||
|
||||
if (settings.$li.length && settings.$target.length > 0) {
|
||||
if(init){ //run when we first start
|
||||
settings.preRideCallback(settings.$li.index(), settings.$next_tip );
|
||||
if(settings.modal){
|
||||
methods.show_modal();
|
||||
}
|
||||
}
|
||||
settings.preStepCallback(settings.$li.index(), settings.$next_tip );
|
||||
|
||||
// parse options
|
||||
opts_arr = (settings.$li.data('options') || ':').split(';');
|
||||
opts_len = opts_arr.length;
|
||||
for (ii = opts_len - 1; ii >= 0; ii--) {
|
||||
p = opts_arr[ii].split(':');
|
||||
|
||||
if (p.length === 2) {
|
||||
opts[$.trim(p[0])] = $.trim(p[1]);
|
||||
}
|
||||
}
|
||||
settings.tipSettings = $.extend({}, settings, opts);
|
||||
settings.tipSettings.tipLocationPattern = settings.tipLocationPatterns[settings.tipSettings.tipLocation];
|
||||
|
||||
if(settings.modal && settings.expose){
|
||||
methods.expose();
|
||||
}
|
||||
|
||||
// scroll if not modal
|
||||
if (!/body/i.test(settings.$target.selector) && settings.scroll) {
|
||||
methods.scroll_to();
|
||||
}
|
||||
|
||||
if (methods.is_phone()) {
|
||||
methods.pos_phone(true);
|
||||
} else {
|
||||
methods.pos_default(true);
|
||||
}
|
||||
|
||||
$timer = $('.joyride-timer-indicator', settings.$next_tip);
|
||||
|
||||
if (/pop/i.test(settings.tipAnimation)) {
|
||||
|
||||
$timer.outerWidth(0);
|
||||
|
||||
if (settings.timer > 0) {
|
||||
|
||||
settings.$next_tip.show();
|
||||
$timer.animate({
|
||||
width: $('.joyride-timer-indicator-wrap', settings.$next_tip).outerWidth()
|
||||
}, settings.timer);
|
||||
|
||||
} else {
|
||||
|
||||
settings.$next_tip.show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else if (/fade/i.test(settings.tipAnimation)) {
|
||||
|
||||
$timer.outerWidth(0);
|
||||
|
||||
if (settings.timer > 0) {
|
||||
|
||||
settings.$next_tip.fadeIn(settings.tipAnimationFadeSpeed);
|
||||
|
||||
settings.$next_tip.show();
|
||||
$timer.animate({
|
||||
width: $('.joyride-timer-indicator-wrap', settings.$next_tip).outerWidth()
|
||||
}, settings.timer);
|
||||
|
||||
} else {
|
||||
|
||||
settings.$next_tip.fadeIn(settings.tipAnimationFadeSpeed);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
settings.$current_tip = settings.$next_tip;
|
||||
// Focus next button for keyboard users.
|
||||
$('.joyride-next-tip', settings.$current_tip).focus();
|
||||
methods.tabbable(settings.$current_tip);
|
||||
// skip non-existent targets
|
||||
} else if (settings.$li && settings.$target.length < 1) {
|
||||
|
||||
methods.show();
|
||||
|
||||
} else {
|
||||
|
||||
methods.end();
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
settings.paused = true;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// detect phones with media queries if supported.
|
||||
is_phone : function () {
|
||||
return false; // 2013-10-29 Adriaan Wormgoor - hard-falsed this
|
||||
|
||||
if (Modernizr) {
|
||||
return Modernizr.mq('only screen and (max-width: 767px)');
|
||||
}
|
||||
|
||||
return (settings.$window.width() < 767) ? true : false;
|
||||
},
|
||||
|
||||
support_localstorage : function () {
|
||||
if (Modernizr) {
|
||||
return Modernizr.localstorage;
|
||||
} else {
|
||||
return !!window.localStorage;
|
||||
}
|
||||
},
|
||||
|
||||
hide : function () {
|
||||
if(settings.modal && settings.expose){
|
||||
methods.un_expose();
|
||||
}
|
||||
if(!settings.modal){
|
||||
$('.joyride-modal-bg').hide();
|
||||
}
|
||||
settings.$current_tip.hide();
|
||||
settings.postStepCallback(settings.$li.index(), settings.$current_tip);
|
||||
},
|
||||
|
||||
set_li : function (init) {
|
||||
if (init) {
|
||||
settings.$li = settings.$tip_content.eq(settings.startOffset);
|
||||
methods.set_next_tip();
|
||||
settings.$current_tip = settings.$next_tip;
|
||||
} else {
|
||||
settings.$li = settings.$li.next();
|
||||
methods.set_next_tip();
|
||||
}
|
||||
|
||||
methods.set_target();
|
||||
},
|
||||
|
||||
set_next_tip : function () {
|
||||
settings.$next_tip = $('.joyride-tip-guide[data-index=' + settings.$li.index() + ']');
|
||||
},
|
||||
|
||||
set_target : function () {
|
||||
var cl = settings.$li.attr('data-class'),
|
||||
id = settings.$li.attr('data-id'),
|
||||
$sel = function () {
|
||||
if (id) {
|
||||
return $(settings.document.getElementById(id));
|
||||
} else if (cl) {
|
||||
return $('.' + cl).filter(":visible").first();
|
||||
} else {
|
||||
return $('body');
|
||||
}
|
||||
};
|
||||
|
||||
settings.$target = $sel();
|
||||
},
|
||||
|
||||
scroll_to : function () {
|
||||
var window_half, tipOffset;
|
||||
|
||||
window_half = settings.$window.height() / 2;
|
||||
tipOffset = Math.ceil(settings.$target.offset().top - window_half + settings.$next_tip.outerHeight());
|
||||
|
||||
$("html, body").stop().animate({
|
||||
scrollTop: tipOffset
|
||||
}, settings.scrollSpeed);
|
||||
},
|
||||
|
||||
paused : function () {
|
||||
if (($.inArray((settings.$li.index() + 1), settings.pauseAfter) === -1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
destroy : function () {
|
||||
if(!$.isEmptyObject(settings)){
|
||||
settings.$document.off('.joyride');
|
||||
}
|
||||
|
||||
$(window).off('.joyride');
|
||||
$('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
|
||||
$('.joyride-tip-guide, .joyride-modal-bg').remove();
|
||||
clearTimeout(settings.automate);
|
||||
settings = {};
|
||||
},
|
||||
|
||||
restart : function () {
|
||||
if(!settings.autoStart)
|
||||
{
|
||||
if (!settings.startTimerOnClick && settings.timer > 0) {
|
||||
methods.show('init');
|
||||
methods.startTimer();
|
||||
} else {
|
||||
methods.show('init');
|
||||
}
|
||||
settings.autoStart = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
methods.hide();
|
||||
settings.$li = undefined;
|
||||
methods.show('init');
|
||||
}
|
||||
},
|
||||
|
||||
pos_default : function (init) {
|
||||
var half_fold = Math.ceil(settings.$window.height() / 2),
|
||||
tip_position = settings.$next_tip.offset(),
|
||||
$nub = $('.joyride-nub', settings.$next_tip),
|
||||
nub_width = Math.ceil($nub.outerWidth() / 2),
|
||||
nub_height = Math.ceil($nub.outerHeight() / 2),
|
||||
toggle = init || false;
|
||||
|
||||
// tip must not be "display: none" to calculate position
|
||||
if (toggle) {
|
||||
settings.$next_tip.css('visibility', 'hidden');
|
||||
settings.$next_tip.show();
|
||||
}
|
||||
|
||||
if (!/body/i.test(settings.$target.selector)) {
|
||||
var
|
||||
topAdjustment = settings.tipSettings.tipAdjustmentY ? parseInt(settings.tipSettings.tipAdjustmentY) : 0,
|
||||
leftAdjustment = settings.tipSettings.tipAdjustmentX ? parseInt(settings.tipSettings.tipAdjustmentX) : 0;
|
||||
|
||||
if (methods.bottom()) {
|
||||
settings.$next_tip.css({
|
||||
top: (settings.$target.offset().top + nub_height + settings.$target.outerHeight() + topAdjustment),
|
||||
left: settings.$target.offset().left - (settings.$next_tip.outerWidth() * 0.70) + leftAdjustment});
|
||||
|
||||
if (/right/i.test(settings.tipSettings.nubPosition)) {
|
||||
settings.$next_tip.css('left', settings.$target.offset().left + settings.$target.outerWidth());
|
||||
}
|
||||
|
||||
methods.nub_position($nub, settings.tipSettings.nubPosition, 'top');
|
||||
|
||||
} else if (methods.top()) {
|
||||
|
||||
settings.$next_tip.css({
|
||||
top: (settings.$target.offset().top - settings.$next_tip.outerHeight() - nub_height - topAdjustment),
|
||||
left: settings.$target.offset().left - (settings.$next_tip.outerWidth() * .8) + leftAdjustment});
|
||||
|
||||
methods.nub_position($nub, settings.tipSettings.nubPosition, 'bottom');
|
||||
|
||||
} else if (methods.right()) {
|
||||
|
||||
settings.$next_tip.css({
|
||||
top: settings.$target.offset().top + (topAdjustment*0.5), // HACK
|
||||
left: (settings.$target.outerWidth() + settings.$target.offset().left + nub_width) + leftAdjustment});
|
||||
|
||||
methods.nub_position($nub, settings.tipSettings.nubPosition, 'left');
|
||||
|
||||
} else if (methods.left()) {
|
||||
|
||||
settings.$next_tip.css({
|
||||
top: settings.$target.offset().top + (topAdjustment*0.5), // HACK
|
||||
left: (settings.$target.offset().left - settings.$next_tip.outerWidth() - nub_width) - leftAdjustment});
|
||||
|
||||
methods.nub_position($nub, settings.tipSettings.nubPosition, 'right');
|
||||
|
||||
}
|
||||
|
||||
if (!methods.visible(methods.corners(settings.$next_tip)) && settings.attempts < settings.tipSettings.tipLocationPattern.length) {
|
||||
|
||||
$nub.removeClass('bottom')
|
||||
.removeClass('top')
|
||||
.removeClass('right')
|
||||
.removeClass('left');
|
||||
|
||||
settings.tipSettings.tipLocation = settings.tipSettings.tipLocationPattern[settings.attempts];
|
||||
|
||||
settings.attempts++;
|
||||
|
||||
methods.pos_default(true);
|
||||
|
||||
}
|
||||
|
||||
} else if (settings.$li.length) {
|
||||
|
||||
methods.pos_modal($nub);
|
||||
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
settings.$next_tip.hide();
|
||||
settings.$next_tip.css('visibility', 'visible');
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
pos_phone : function (init) {
|
||||
var tip_height = settings.$next_tip.outerHeight(),
|
||||
tip_offset = settings.$next_tip.offset(),
|
||||
target_height = settings.$target.outerHeight(),
|
||||
$nub = $('.joyride-nub', settings.$next_tip),
|
||||
nub_height = Math.ceil($nub.outerHeight() / 2),
|
||||
toggle = init || false;
|
||||
|
||||
$nub.removeClass('bottom')
|
||||
.removeClass('top')
|
||||
.removeClass('right')
|
||||
.removeClass('left');
|
||||
|
||||
if (toggle) {
|
||||
settings.$next_tip.css('visibility', 'hidden');
|
||||
settings.$next_tip.show();
|
||||
}
|
||||
|
||||
if (!/body/i.test(settings.$target.selector)) {
|
||||
|
||||
if (methods.top()) {
|
||||
|
||||
settings.$next_tip.offset({top: settings.$target.offset().top - tip_height - nub_height});
|
||||
$nub.addClass('bottom');
|
||||
|
||||
} else {
|
||||
|
||||
settings.$next_tip.offset({top: settings.$target.offset().top + target_height + nub_height});
|
||||
$nub.addClass('top');
|
||||
|
||||
}
|
||||
|
||||
} else if (settings.$li.length) {
|
||||
|
||||
methods.pos_modal($nub);
|
||||
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
settings.$next_tip.hide();
|
||||
settings.$next_tip.css('visibility', 'visible');
|
||||
}
|
||||
},
|
||||
|
||||
pos_modal : function ($nub) {
|
||||
methods.center();
|
||||
$nub.hide();
|
||||
|
||||
methods.show_modal();
|
||||
|
||||
},
|
||||
|
||||
show_modal : function() {
|
||||
if ($('.joyride-modal-bg').length < 1) {
|
||||
$('body').append(settings.template.modal).show();
|
||||
}
|
||||
|
||||
if (/pop/i.test(settings.tipAnimation)) {
|
||||
$('.joyride-modal-bg').show();
|
||||
} else {
|
||||
$('.joyride-modal-bg').fadeIn(settings.tipAnimationFadeSpeed);
|
||||
}
|
||||
},
|
||||
|
||||
expose: function(){
|
||||
var expose,
|
||||
exposeCover,
|
||||
el,
|
||||
origCSS,
|
||||
randId = 'expose-'+Math.floor(Math.random()*10000);
|
||||
if (arguments.length>0 && arguments[0] instanceof $){
|
||||
el = arguments[0];
|
||||
} else if(settings.$target && !/body/i.test(settings.$target.selector)){
|
||||
el = settings.$target;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if(el.length < 1){
|
||||
if(window.console){
|
||||
console.error('element not valid', el);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
expose = $(settings.template.expose);
|
||||
settings.$body.append(expose);
|
||||
// console.log("JOYRIDE >> EXPOSE INFO >> el[0].clientWidth: " + el[0].clientWidth + ", el: " , el , ", el[0]: " , el[0] , ", el.offset: " , el.offset() , ", el.clientWidth: " + el.clientWidth + ", el.outerWidth: " + el.outerWidth(true))
|
||||
// console.log("JOYRIDE >> EXPOSE INFO >> el.css('margin'): " + el.css('margin'));
|
||||
// console.log("JOYRIDE >> EXPOSE INFO >> el.css('margin-left'): " + el.css('margin-left'));
|
||||
expose.css({
|
||||
// margin: el.css('margin'),
|
||||
top: el.offset().top - 2, // CAVEMAN PADDING!
|
||||
left: el.offset().left - 2, // CAVEMAN PADDING!
|
||||
width: el[0].clientWidth + 4, // CAVEMAN PADDING!
|
||||
height: el[0].clientHeight + 4 // CAVEMAN PADDING!
|
||||
// width: el.outerWidth(true),
|
||||
// height: el.outerHeight(true)
|
||||
});
|
||||
exposeCover = $(settings.template.exposeCover);
|
||||
origCSS = {
|
||||
zIndex: el.css('z-index'),
|
||||
position: el.css('position')
|
||||
};
|
||||
el.css('z-index',expose.css('z-index')*1+1);
|
||||
if(origCSS.position == 'static'){
|
||||
el.css('position','relative');
|
||||
}
|
||||
el.data('expose-css',origCSS);
|
||||
exposeCover.css({
|
||||
top: el.offset().top - 2, // CAVEMAN PADDING!
|
||||
left: el.offset().left - 2, // CAVEMAN PADDING!
|
||||
width: el[0].clientWidth + 4, // CAVEMAN PADDING!
|
||||
height: el[0].clientHeight + 4 // CAVEMAN PADDING!
|
||||
// top: el.offset().top,
|
||||
// left: el.offset().left,
|
||||
// width: el.outerWidth(true),
|
||||
// height: el.outerHeight(true)
|
||||
});
|
||||
settings.$body.append(exposeCover);
|
||||
expose.addClass(randId);
|
||||
exposeCover.addClass(randId);
|
||||
if(settings.tipSettings['exposeClass']){
|
||||
expose.addClass(settings.tipSettings['exposeClass']);
|
||||
exposeCover.addClass(settings.tipSettings['exposeClass']);
|
||||
}
|
||||
el.data('expose', randId);
|
||||
settings.postExposeCallback(settings.$li.index(), settings.$next_tip, el);
|
||||
methods.add_exposed(el);
|
||||
},
|
||||
|
||||
un_expose: function(){
|
||||
var exposeId,
|
||||
el,
|
||||
expose ,
|
||||
origCSS,
|
||||
clearAll = false;
|
||||
if (arguments.length>0 && arguments[0] instanceof $){
|
||||
el = arguments[0];
|
||||
} else if(settings.$target && !/body/i.test(settings.$target.selector)){
|
||||
el = settings.$target;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if(el.length < 1){
|
||||
if(window.console){
|
||||
console.error('element not valid', el);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exposeId = el.data('expose');
|
||||
expose = $('.'+exposeId);
|
||||
if(arguments.length>1){
|
||||
clearAll = arguments[1];
|
||||
}
|
||||
if(clearAll === true){
|
||||
$('.joyride-expose-wrapper,.joyride-expose-cover').remove();
|
||||
} else {
|
||||
expose.remove();
|
||||
}
|
||||
origCSS = el.data('expose-css');
|
||||
if(origCSS.zIndex == 'auto'){
|
||||
el.css('z-index', '');
|
||||
} else {
|
||||
el.css('z-index',origCSS.zIndex);
|
||||
}
|
||||
if(origCSS.position != el.css('position')){
|
||||
if(origCSS.position == 'static'){// this is default, no need to set it.
|
||||
el.css('position', '');
|
||||
} else {
|
||||
el.css('position',origCSS.position);
|
||||
}
|
||||
}
|
||||
el.removeData('expose');
|
||||
el.removeData('expose-z-index');
|
||||
methods.remove_exposed(el);
|
||||
},
|
||||
|
||||
add_exposed: function(el){
|
||||
settings.exposed = settings.exposed || [];
|
||||
if(el instanceof $){
|
||||
settings.exposed.push(el[0]);
|
||||
} else if(typeof el == 'string'){
|
||||
settings.exposed.push(el);
|
||||
}
|
||||
},
|
||||
|
||||
remove_exposed: function(el){
|
||||
var search;
|
||||
if(el instanceof $){
|
||||
search = el[0]
|
||||
} else if (typeof el == 'string'){
|
||||
search = el;
|
||||
}
|
||||
settings.exposed = settings.exposed || [];
|
||||
for(var i=0; i<settings.exposed.length; i++){
|
||||
if(settings.exposed[i] == search){
|
||||
settings.exposed.splice(i,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
center : function () {
|
||||
var $w = settings.$window;
|
||||
|
||||
settings.$next_tip.css({
|
||||
top : ((($w.height() - settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()),
|
||||
left : ((($w.width() - settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft())
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
bottom : function () {
|
||||
return /bottom/i.test(settings.tipSettings.tipLocation);
|
||||
},
|
||||
|
||||
top : function () {
|
||||
return /top/i.test(settings.tipSettings.tipLocation);
|
||||
},
|
||||
|
||||
right : function () {
|
||||
return /right/i.test(settings.tipSettings.tipLocation);
|
||||
},
|
||||
|
||||
left : function () {
|
||||
return /left/i.test(settings.tipSettings.tipLocation);
|
||||
},
|
||||
|
||||
corners : function (el) {
|
||||
var w = settings.$window,
|
||||
window_half = w.height() / 2,
|
||||
tipOffset = Math.ceil(settings.$target.offset().top - window_half + settings.$next_tip.outerHeight()),//using this to calculate since scroll may not have finished yet.
|
||||
right = w.width() + w.scrollLeft(),
|
||||
offsetBottom = w.height() + tipOffset,
|
||||
bottom = w.height() + w.scrollTop(),
|
||||
top = w.scrollTop();
|
||||
|
||||
if(tipOffset < top){
|
||||
if (tipOffset <0 ){
|
||||
top = 0;
|
||||
} else {
|
||||
top = tipOffset;
|
||||
}
|
||||
}
|
||||
|
||||
if(offsetBottom > bottom){
|
||||
bottom = offsetBottom;
|
||||
}
|
||||
|
||||
return [
|
||||
el.offset().top < top,
|
||||
right < el.offset().left + el.outerWidth(),
|
||||
bottom < el.offset().top + el.outerHeight(),
|
||||
w.scrollLeft() > el.offset().left
|
||||
];
|
||||
},
|
||||
|
||||
visible : function (hidden_corners) {
|
||||
var i = hidden_corners.length;
|
||||
|
||||
while (i--) {
|
||||
if (hidden_corners[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
nub_position : function (nub, pos, def) {
|
||||
if (pos === 'auto') {
|
||||
nub.addClass(def);
|
||||
} else {
|
||||
nub.addClass(pos);
|
||||
}
|
||||
},
|
||||
|
||||
startTimer : function () {
|
||||
if (settings.$li.length) {
|
||||
settings.automate = setTimeout(function () {
|
||||
methods.hide();
|
||||
methods.show();
|
||||
methods.startTimer();
|
||||
}, settings.timer);
|
||||
} else {
|
||||
clearTimeout(settings.automate);
|
||||
}
|
||||
},
|
||||
|
||||
end : function () {
|
||||
if (settings.cookieMonster) {
|
||||
$.cookie(settings.cookieName, 'ridden', { expires: 365, domain: settings.cookieDomain, path: settings.cookiePath });
|
||||
}
|
||||
|
||||
if (settings.localStorage) {
|
||||
localStorage.setItem(settings.localStorageKey, true);
|
||||
}
|
||||
|
||||
if (settings.timer > 0) {
|
||||
clearTimeout(settings.automate);
|
||||
}
|
||||
if(settings.modal && settings.expose){
|
||||
methods.un_expose();
|
||||
}
|
||||
if (settings.$current_tip) {
|
||||
settings.$current_tip.hide();
|
||||
}
|
||||
if (settings.$li) {
|
||||
settings.postStepCallback(settings.$li.index(), settings.$current_tip);
|
||||
settings.postRideCallback(settings.$li.index(), settings.$current_tip);
|
||||
}
|
||||
$('.joyride-modal-bg').hide();
|
||||
},
|
||||
|
||||
jquery_check : function () {
|
||||
// define on() and off() for older jQuery
|
||||
if (!$.isFunction($.fn.on)) {
|
||||
|
||||
$.fn.on = function (types, sel, fn) {
|
||||
|
||||
return this.delegate(sel, types, fn);
|
||||
|
||||
};
|
||||
|
||||
$.fn.off = function (types, sel, fn) {
|
||||
|
||||
return this.undelegate(sel, types, fn);
|
||||
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
outerHTML : function (el) {
|
||||
// support FireFox < 11
|
||||
return el.outerHTML || new XMLSerializer().serializeToString(el);
|
||||
},
|
||||
|
||||
version : function () {
|
||||
return settings.version;
|
||||
},
|
||||
|
||||
tabbable : function (el) {
|
||||
$(el).on('keydown', function( event ) {
|
||||
if (!event.isDefaultPrevented() && event.keyCode &&
|
||||
// Escape key.
|
||||
event.keyCode === 27 ) {
|
||||
event.preventDefault();
|
||||
methods.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent tabbing out of tour items.
|
||||
if ( event.keyCode !== 9 ) {
|
||||
return;
|
||||
}
|
||||
var tabbables = $(el).find(":tabbable"),
|
||||
first = tabbables.filter(":first"),
|
||||
last = tabbables.filter(":last");
|
||||
if ( event.target === last[0] && !event.shiftKey ) {
|
||||
first.focus( 1 );
|
||||
event.preventDefault();
|
||||
} else if ( event.target === first[0] && event.shiftKey ) {
|
||||
last.focus( 1 );
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$.fn.joyride = function (method) {
|
||||
if (methods[method]) {
|
||||
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||
} else if (typeof method === 'object' || !method) {
|
||||
return methods.init.apply(this, arguments);
|
||||
} else {
|
||||
$.error('Method ' + method + ' does not exist on jQuery.joyride');
|
||||
}
|
||||
};
|
||||
|
||||
}(jQuery, this));
|
123
js/main.js
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var debugMode = false; // debug mode
|
||||
var sendPrintCommands = true; // if Doodle3d should send print commands to the 3d printer
|
||||
var communicateWithWifibox = true; // if Doodle3d should try interfacing with the wifibox (in case one is not connected)
|
||||
|
@ -5,31 +13,56 @@ var wifiboxIsRemote = false; // when you want to run the client on a comp
|
|||
var autoUpdate = true; // auto retrieve updates about temperature and progress from printer
|
||||
|
||||
var printer = new Printer();
|
||||
var progressbar = new Progressbar();
|
||||
var thermometer = new Thermometer();
|
||||
var settingsWindow = new SettingsWindow();
|
||||
var message = new Message();
|
||||
|
||||
var firstTimeSettingsLoaded = true;
|
||||
|
||||
var wifiboxURL; // Using the uhttpd lua handler as default, because of better performance
|
||||
var wifiboxCGIBinURL; // CGI-bin, for some network stuff, where it needs to restart the webserver for example
|
||||
|
||||
var $drawAreaContainer, $doodleCanvas, doodleCanvas, doodleCanvasContext, $previewContainer;
|
||||
|
||||
var showhideInterval;
|
||||
var showOrHide = false;
|
||||
|
||||
var clientInfo = {};
|
||||
|
||||
var POPUP_SHOW_DURATION = 175;
|
||||
var BUTTON_GROUP_SHOW_DURATION = 80;
|
||||
|
||||
$(function() {
|
||||
console.log("ready");
|
||||
|
||||
|
||||
//TODO give this a more logical place in code
|
||||
|
||||
console.log("Doodle3D client ready");
|
||||
console.log("Build information - <%= build_info %>)");
|
||||
|
||||
if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1");
|
||||
if (getURLParameter("p") != "null") sendPrintCommands = (getURLParameter("p") == "1");
|
||||
if (getURLParameter("c") != "null") communicateWithWifibox = (getURLParameter("c") == "1");
|
||||
if (getURLParameter("r") != "null") wifiboxIsRemote = (getURLParameter("r") == "1");
|
||||
if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1");
|
||||
|
||||
var hostname;
|
||||
if (wifiboxIsRemote) hostname = 'http://192.168.5.1';
|
||||
if (getURLParameter("wifiboxURL") != "null") hostname = getURLParameter("wifiboxURL");
|
||||
if (!hostname) hostname = "http://" + window.location.host;
|
||||
|
||||
wifiboxURL = hostname+"/d3dapi";
|
||||
wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
|
||||
|
||||
|
||||
if (wifiboxIsRemote) {
|
||||
wifiboxURL = "http://192.168.5.1/cgi-bin/d3dapi";
|
||||
} else {
|
||||
wifiboxURL = "http://" + window.location.host + "/d3dapi";
|
||||
}
|
||||
//var api = wifiboxURL+'/d3dapi/sketch/';
|
||||
|
||||
// if (wifiboxIsRemote) {
|
||||
// // var hostname = "http://10.0.0.45";
|
||||
// var hostname = "http://192.168.5.1";
|
||||
// wifiboxURL = hostname+"/d3dapi";
|
||||
// wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
|
||||
// } else {
|
||||
// wifiboxURL = "http://" + window.location.host + "/d3dapi";
|
||||
// wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
||||
// }
|
||||
|
||||
if (!communicateWithWifibox) {
|
||||
sendPrintCommands = false; // 'communicateWithWifibox = false' implies this
|
||||
|
@ -40,29 +73,47 @@ $(function() {
|
|||
console.log("wifiboxIsRemote: " + wifiboxIsRemote);
|
||||
console.log("wifibox URL: " + wifiboxURL);
|
||||
|
||||
// rudimentary client info
|
||||
clientInfo.isMobileDevice = isMobileDevice();
|
||||
clientInfo.isSmartphone = isSmartphone();
|
||||
|
||||
initDoodleDrawing();
|
||||
initPreviewRendering();
|
||||
initLayouting();
|
||||
initSidebars();
|
||||
// initSidebars();
|
||||
initButtonBehavior();
|
||||
initVerticalShapes();
|
||||
initKeyboard();
|
||||
// initVerticalShapes();
|
||||
initWordArt();
|
||||
initShapeDialog();
|
||||
initScanDialog();
|
||||
|
||||
disableDragging();
|
||||
|
||||
if (!clientInfo.isSmartphone) initHelp();
|
||||
|
||||
thermometer.init($("#thermometerCanvas"), $("#thermometerContainer"));
|
||||
progressbar.init($("#progressbarCanvas"), $("#progressbarCanvasContainer"));
|
||||
|
||||
message.init($("#message"));
|
||||
|
||||
printer.init();
|
||||
$(document).on(Printer.UPDATE,update);
|
||||
|
||||
settingsWindow.init(wifiboxURL);
|
||||
settingsWindow.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
$(document).on(SettingsWindow.SETTINGS_LOADED, settingsLoaded);
|
||||
|
||||
|
||||
if(debugMode) {
|
||||
console.log("debug mode is true");
|
||||
$("body").css("overflow", "auto");
|
||||
$("#debug_textArea").css("display", "block");
|
||||
$("#preview_tmp").css("display", "block");
|
||||
|
||||
//$("#preview_tmp").css("display", "block");
|
||||
|
||||
$("#debug_display").css("display", "block");
|
||||
|
||||
|
||||
// show and hide the progressguage and thermometer
|
||||
//showhideInterval = setInterval(showOrHideThermo, 2500);
|
||||
|
||||
// $("#debugContainer").css("display", "block");
|
||||
|
||||
/* TEMP CODE!! -> artificially populates the startgcode and endgcode textareas in the settings window */
|
||||
|
@ -89,17 +140,45 @@ $(function() {
|
|||
}, 1000);
|
||||
//*/
|
||||
}
|
||||
});
|
||||
|
||||
function disableDragging() {
|
||||
$(document).bind("dragstart", function(event) {
|
||||
console.log("dragstart");
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
function showOrHideThermo() {
|
||||
console.log("f:showOrHideThermo()");
|
||||
if (showOrHide) {
|
||||
thermometer.hide();
|
||||
progressbar.hide();
|
||||
} else {
|
||||
thermometer.show();
|
||||
progressbar.show();
|
||||
|
||||
}
|
||||
showOrHide = !showOrHide;
|
||||
}
|
||||
|
||||
})
|
||||
function settingsLoaded() {
|
||||
console.log("settingsLoaded");
|
||||
console.log("autoHeatup: ",settings["printer.heatup.enabled"]);
|
||||
if(settings["printer.heatup.enabled"]) {
|
||||
if(firstTimeSettingsLoaded) {
|
||||
|
||||
if(firstTimeSettingsLoaded) {
|
||||
console.log(" preheat: ",settings["printer.heatup.enabled"]);
|
||||
console.log(" state: ",state);
|
||||
if(state == Printer.IDLE_STATE && settings["printer.heatup.enabled"]) {
|
||||
printer.preheat();
|
||||
firstTimeSettingsLoaded = false;
|
||||
}
|
||||
console.log("doodle3d.tour.enabled: ",settings["doodle3d.tour.enabled"]);
|
||||
if(settings["doodle3d.tour.enabled"] && !clientInfo.isSmartphone) {
|
||||
console.log("show tour");
|
||||
initHelp();
|
||||
}
|
||||
firstTimeSettingsLoaded = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function setDebugText(text) {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
//*
|
||||
var $preview;
|
||||
var preview;
|
||||
|
@ -7,7 +15,7 @@ var preview_tmp;
|
|||
var previewCtx_tmp;
|
||||
|
||||
var previewDefaults = {
|
||||
rotation: Math.PI/90,
|
||||
rotation: 0, //Math.PI/90,
|
||||
numLayers: 10
|
||||
}
|
||||
|
||||
|
@ -18,7 +26,7 @@ var prevRedrawTime = new Date().getTime();
|
|||
var redrawInterval = 1000 / 30; // ms
|
||||
|
||||
function initPreviewRendering() {
|
||||
console.log("f:initPreviewRendering()");
|
||||
//console.log("f:initPreviewRendering()");
|
||||
|
||||
$preview = $("#preview");
|
||||
preview = $preview[0];
|
||||
|
@ -33,12 +41,17 @@ function initPreviewRendering() {
|
|||
|
||||
previewCtx_tmp = preview_tmp.getContext('2d');
|
||||
|
||||
// doodleImageCapture = new Image();
|
||||
|
||||
calcPreviewCanvasProperties();
|
||||
redrawPreview();
|
||||
|
||||
// needed to
|
||||
// doodleImageCapture = new Image();
|
||||
}
|
||||
|
||||
function calcPreviewCanvasProperties() {
|
||||
console.log("f:calcPreviewCanvasProperties()");
|
||||
// console.log("f:calcPreviewCanvasProperties()");
|
||||
|
||||
globalScale = preview.width / canvasWidth;
|
||||
layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
|
@ -76,9 +89,13 @@ var highlight = true; //highlight bottom, middle and top layers
|
|||
var linesRaw = "";
|
||||
var debug_redrawSimplification = 6;
|
||||
function redrawPreview(redrawLess) {
|
||||
//console.log("PreviewRendering:redrawPreview");
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
|
||||
if (_points.length < 2) return;
|
||||
if (_points.length < 2) {
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!redrawLess) {
|
||||
//debug_redrawSimplification = Math.round(_points.length / 65);
|
||||
|
@ -152,8 +169,7 @@ function redrawPreview(redrawLess) {
|
|||
}
|
||||
|
||||
function renderToImageDataPreview() {
|
||||
console.log("f:renderToImageDataPreview()");
|
||||
|
||||
//console.log("PreviewRendering:renderToImageDataPreview");
|
||||
if (_points.length < 2) return;
|
||||
|
||||
//*
|
||||
|
@ -222,11 +238,12 @@ function renderToImageDataPreview() {
|
|||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
// called by the move up/down or twist left/right buttons
|
||||
// called by the move up/down, twist left/right or new buttons
|
||||
// it is assumed that the preview has been rendered to an Image object, which will be used to draw the preview with (much better performance)
|
||||
function redrawRenderedPreview(redrawLess) {
|
||||
//console.log("PreviewRendering:redrawRenderedPreview");
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
console.log("f:redrawRenderedPreview()");
|
||||
// console.log("f:redrawRenderedPreview()");
|
||||
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
|
@ -234,7 +251,10 @@ function redrawRenderedPreview(redrawLess) {
|
|||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
|
||||
// check if there is preview image data that we can use for the layers
|
||||
if(!doodleImageCapture.src || doodleImageCapture.src == "") return;
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
var verticalScaleFactor = scaleFunction(i / maxNumLayers);
|
||||
|
@ -257,7 +277,7 @@ function redrawRenderedPreview(redrawLess) {
|
|||
previewCtx.scale(verticalScaleFactor, scaleY * verticalScaleFactor);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate(-layerCX,-layerCY);
|
||||
|
||||
|
||||
previewCtx.drawImage(doodleImageCapture, 0, 0);
|
||||
|
||||
y -= yStep;
|
||||
|
@ -283,6 +303,7 @@ function centeredAndScaledDoodlePoint(p) {
|
|||
var updatePrevX = -1;
|
||||
var updatePrevY = -1;
|
||||
function updatePreview(_x, _y, redrawLess) {
|
||||
//console.log("PreviewRendering:updatePreview");
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
redrawLess = false;
|
||||
|
||||
|
@ -340,4 +361,4 @@ function updatePreview(_x, _y, redrawLess) {
|
|||
updatePrevY = _y;
|
||||
|
||||
}
|
||||
//*/
|
||||
//*/
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
//*
|
||||
var $preview;
|
||||
var preview;
|
||||
var previewCtx;
|
||||
|
||||
$preview = $("#preview");
|
||||
preview = document.getElementById('preview');
|
||||
previewCtx = preview.getContext('2d');
|
||||
|
||||
var svgPathRegExp = /[LM]\d* \d*/ig;
|
||||
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/;
|
||||
|
||||
var prevRedrawTime = new Date().getTime();
|
||||
var redrawInterval = 1000 / 30; // ms
|
||||
|
||||
function initPreviewRendering() {
|
||||
console.log("f:initPreviewRendering()");
|
||||
|
||||
layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
layerCY = (canvasHeight / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
yStep = preview.height / 150;
|
||||
|
||||
redrawPreview();
|
||||
}
|
||||
|
||||
//var numLayers = 100; //50
|
||||
var numLayers = 100; // 100
|
||||
var globalScale = 0.3; // global scale of preview (width preview / width canvas)
|
||||
var globalAlpha = 0.20; // global alpha of preview
|
||||
var scaleY = 0.4; // additional vertical scale per path for 3d effect
|
||||
var viewerScale = 0.65; // additional scale to fit into preview nicely (otherwise is fills out totally)
|
||||
var strokeWidth = 2; //4;
|
||||
//var rStep = Math.PI/40; //Math.PI/40; //
|
||||
var rStep = Math.PI/45; // Math.PI/180; //Math.PI/40; //
|
||||
var yStep = preview.height / 150; // 3; //6;
|
||||
//var svgWidth = 500; // 650 //parseInt($(svg).css("width"));
|
||||
//var svgHeight = 450; //450; //parseInt($(svg).css("height"));
|
||||
var layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
var layerCY = (canvasHeight / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
var layerOffsetY= preview.height - 1.75 * layerCY; // 330; // previewHeight - 120
|
||||
var prevX = 0;
|
||||
var prevY = 0;
|
||||
var highlight = true; //highlight bottom, middle and top layers
|
||||
|
||||
var linesRaw = "";
|
||||
var debug_redrawSimplification = 6;
|
||||
function redrawPreview(redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
//*/
|
||||
//TODO
|
||||
/*
|
||||
het up/down en twist left/right gaat nu wat traag. Juist dat gaat veel sneller met de toDataURL oplossing
|
||||
Is het een idee om op het einde van een touchevent wel de image versie te renderen maar tijdens het tekenen
|
||||
niet?
|
||||
*/
|
||||
|
||||
if (!redrawLess) {
|
||||
//debug_redrawSimplification = Math.round(_points.length / 65);
|
||||
//*
|
||||
if (_points.length < 100) {
|
||||
debug_redrawSimplification = 6;
|
||||
} else if (_points.length < 250) {
|
||||
debug_redrawSimplification = 7;
|
||||
} else if (_points.length < 400) {
|
||||
debug_redrawSimplification = 8;
|
||||
} else if (_points.length < 550) {
|
||||
debug_redrawSimplification = 9;
|
||||
} else if (_points.length < 700) {
|
||||
debug_redrawSimplification = 10;
|
||||
} else {
|
||||
debug_redrawSimplification = 11;
|
||||
}
|
||||
//*/
|
||||
// console.log("debug_redrawSimplification: " + debug_redrawSimplification);
|
||||
}
|
||||
|
||||
if (_points.length < 2) return;
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
//preview.width = preview.width;
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) {
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
if (redrawLess && i%debug_redrawSimplification != 0 && !(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) ) {
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
continue;
|
||||
}
|
||||
|
||||
previewCtx.save();
|
||||
|
||||
previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
|
||||
// previewCtx.setTransform(1, 0, 0, scaleY, layerCX, layerOffsetY+layerCY+y);
|
||||
previewCtx.scale(viewerScale, scaleY * viewerScale);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate((-doodleTransform[0]) * (globalScale * doodleTransform[2]), (-doodleTransform[1]) * (globalScale * doodleTransform[3]));
|
||||
// previewCtx.translate(-layerCX,-layerCY);
|
||||
// previewCtx.translate(-doodleTransform[0] * globalScale, -doodleTransform[1] * globalScale);
|
||||
|
||||
// previewCtx.setTransform(doodleTransform[2], 0, 0, doodleTransform[3], 0, 0);
|
||||
|
||||
var adjustedDoodlePoint = centeredAndScaledDoodlePoint(_points[0]);
|
||||
|
||||
previewCtx.beginPath();
|
||||
previewCtx.moveTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
for(var j = 1; j < _points.length; j++) {
|
||||
adjustedDoodlePoint = centeredAndScaledDoodlePoint(_points[j])
|
||||
// if (redrawLess && Math.floor(j/debug_redrawSimplification)%2 == 0 ) continue;
|
||||
// if (redrawLess && Math.floor(j/debug_redrawSimplification)%2 == 0 ) continue;
|
||||
if (redrawLess && j%debug_redrawSimplification != 0 ) continue;
|
||||
previewCtx.lineTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
}
|
||||
previewCtx.stroke();
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
function centeredAndScaledDoodlePoint(p) {
|
||||
var obj = { x: 0, y: 0};
|
||||
|
||||
obj.x = (p[0] - ((doodleBounds[2] - doodleBounds[0])/2)) * (globalScale * doodleTransform[2]);
|
||||
obj.y = (p[1] - ((doodleBounds[3] - doodleBounds[1])/2)) * (globalScale * doodleTransform[3]);
|
||||
// obj.x = (p[0] - (doodleBounds[2] - doodleBounds[0])) * (globalScale * doodleTransform[2]);
|
||||
// obj.y = (p[1] - (doodleBounds[3] - doodleBounds[1])) * (globalScale * doodleTransform[3]);
|
||||
// obj.x = (p[0] - doodleTransform[0]) * (globalScale * doodleTransform[2]);
|
||||
// obj.y = (p[1] - doodleTransform[1]) * (globalScale * doodleTransform[3]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//*
|
||||
var updatePrevX = -1;
|
||||
var updatePrevY = -1;
|
||||
function updatePreview(_x, _y, redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
redrawLess = false;
|
||||
|
||||
if (_points.length < 2) return;
|
||||
if (updatePrevX == -1 || updatePrevY == -1) {
|
||||
updatePrevX = _x;
|
||||
updatePrevY = _y;
|
||||
return;
|
||||
}
|
||||
|
||||
// if (_points.length < 16 && Math.sqrt(Math.pow((updatePrevX - _x), 2) + Math.pow((updatePrevY - _y), 2)) < 8) return;
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) {
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
if (redrawLess && i%debug_redrawSimplification != 0 && !(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) ) {
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
continue;
|
||||
}
|
||||
|
||||
previewCtx.save();
|
||||
|
||||
previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
|
||||
previewCtx.scale(viewerScale, scaleY * viewerScale);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate((-doodleTransform[0]) * (globalScale * doodleTransform[2]), (-doodleTransform[1]) * (globalScale * doodleTransform[3]));
|
||||
|
||||
|
||||
previewCtx.beginPath();
|
||||
var prevPoint = centeredAndScaledDoodlePoint([updatePrevX, updatePrevY]);
|
||||
previewCtx.moveTo(prevPoint.x, prevPoint.y);
|
||||
var adjustedDoodlePoint = centeredAndScaledDoodlePoint([_x, _y]);
|
||||
previewCtx.lineTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
previewCtx.stroke();
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
updatePrevX = _x;
|
||||
updatePrevY = _y;
|
||||
|
||||
}
|
||||
//*/
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function FormPanel() {
|
||||
|
||||
var _configAPI = new ConfigAPI();
|
||||
var _retryDelay = 2000;
|
||||
var _retrySaveSettingsDelay;
|
||||
var _retryLoadAllSettingsDelay;
|
||||
var _retryLoadSettingsDelay;
|
||||
var _retryResetSettingsDelay;
|
||||
|
||||
// ui elements
|
||||
var _element;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL,panelElement) {
|
||||
|
||||
// make _self the scope of which init was called?
|
||||
// needed to have the subclass instance access the same counter
|
||||
//_self = this;
|
||||
//console.log(" _element: ",_element);
|
||||
_element = panelElement;
|
||||
//console.log(" >_element: ",_element);
|
||||
_configAPI.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
};
|
||||
|
||||
//this.readForm = function(form) {
|
||||
this.readForm = function(form) {
|
||||
//console.log("FormPanel:readForm");
|
||||
if(!form) form = _element; // if no form specified, read whole panel form
|
||||
//console.log("FormPanel");
|
||||
var settings = {};
|
||||
// Read all selects
|
||||
var selects = form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
//var fieldName = elem.attr('name');
|
||||
if(elem.attr('name') != "") {
|
||||
settings[elem.attr('name')] = elem.val();
|
||||
}
|
||||
});
|
||||
// Read all inputs
|
||||
var inputs = form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
if(elem.attr('name') != "") {
|
||||
switch(elem.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
settings[elem.attr('name')] = elem.val();
|
||||
break;
|
||||
case "checkbox":
|
||||
settings[elem.attr('name')] = elem.prop('checked');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Read all textareas
|
||||
var textareas = form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
settings[elem.attr('name')] = elem.val();
|
||||
});
|
||||
return settings;
|
||||
};
|
||||
|
||||
this.fillForm = function(settings,form) {
|
||||
//console.log("FormPanel:fillForm");
|
||||
if(!form) form = _element; // if no form specified, fill whole panel form
|
||||
//console.log(" form: ",form);
|
||||
|
||||
clearValidationErrors();
|
||||
|
||||
//fill form with loaded settings
|
||||
var selects = form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
elem.val(settings[elem.attr('name')]);
|
||||
});
|
||||
var inputs = form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
|
||||
switch(elem.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
elem.val(settings[elem.attr('name')]);
|
||||
break;
|
||||
case "checkbox":
|
||||
elem.prop('checked', settings[elem.attr('name')]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
var textareas = form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var elem = $(element);
|
||||
var value = settings[elem.attr('name')];
|
||||
elem.val(value);
|
||||
});
|
||||
};
|
||||
|
||||
this.saveSettings = function(newSettings,complete) {
|
||||
//console.log(" newSettings: ",newSettings);
|
||||
_configAPI.save(newSettings,function(data) {
|
||||
var validation = data.validation;
|
||||
//console.log(" validation: ",validation);
|
||||
clearValidationErrors();
|
||||
var validated = true;
|
||||
$.each(validation, function(key, val) {
|
||||
if (val != "ok") {
|
||||
console.log("ERROR: setting '" + key + "' not successfully set. Message: " + val);
|
||||
displayValidationError(key,val);
|
||||
validated = false;
|
||||
}
|
||||
});
|
||||
if(complete) complete(validated, data);
|
||||
}, function() {
|
||||
console.log("Settings:saveSettings: failed");
|
||||
clearTimeout(_retrySaveSettingsDelay);
|
||||
_retrySaveSettingsDelay = setTimeout(function() { _self.saveSettings(newSettings,complete); },_retryDelay); // retry after delay
|
||||
});
|
||||
};
|
||||
function displayValidationError(key,msg) {
|
||||
var formElement = _element.find("[name|='"+key+"']");
|
||||
formElement.addClass("error");
|
||||
var errorMsg = "<p class='errorMsg'>"+msg+"</p>";
|
||||
formElement.after(errorMsg);
|
||||
};
|
||||
function clearValidationErrors() {
|
||||
_element.find(".errorMsg").remove();
|
||||
_element.find(".error").removeClass("error");
|
||||
};
|
||||
|
||||
this.loadAllSettings = function(complete) {
|
||||
_configAPI.loadAll(complete,function() {
|
||||
clearTimeout(_retryLoadAllSettingsDelay);
|
||||
_retryLoadAllSettingsDelay = setTimeout(function() { _self.loadAllSettings(complete); },_retryDelay); // retry after delay
|
||||
});
|
||||
};
|
||||
this.loadSettings = function(targetSettings,complete) {
|
||||
_configAPI.load(targetSettings,complete,function() {
|
||||
clearTimeout(_retryLoadSettingsDelay);
|
||||
_retryLoadSettingsDelay = setTimeout(function() { _self.loadSettings(targetSettings,complete); },_retryDelay); // retry after delay
|
||||
});
|
||||
};
|
||||
|
||||
this.resetAllSettings = function(complete) {
|
||||
_configAPI.resetAll(complete,function() {
|
||||
clearTimeout(_retryResetSettingsDelay);
|
||||
_retryResetSettingsDelay = setTimeout(function() { _self.resetAllSettings(complete); },_retryDelay); // retry after delay
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function NetworkPanel() {
|
||||
|
||||
var NOT_CONNECTED = "not connected"; // used as first item in networks list
|
||||
|
||||
// network mode
|
||||
NetworkPanel.NETWORK_MODE = {
|
||||
NEITHER: "neither",
|
||||
CLIENT: "clientMode",
|
||||
ACCESS_POINT: "accessPointMode"
|
||||
};
|
||||
var _networkMode = NetworkPanel.NETWORK_MODE.NEITHER;
|
||||
var _networkModeChangedHandler;
|
||||
|
||||
var _form = new FormPanel();
|
||||
var _api = new NetworkAPI();
|
||||
var _networks = {};
|
||||
var _currentNetwork; // the ssid of the network the box is on
|
||||
var _selectedNetwork; // the ssid of the selected network in the client mode settings
|
||||
var _substituted_ssid; // the substituted ssid (displayed during creation)
|
||||
var _currentLocalIP = "";
|
||||
var _currentAP;
|
||||
var _currentNetworkStatus;
|
||||
|
||||
var _retryDelay = 2000;
|
||||
//var _retryRefreshNetworksDelay;
|
||||
var _retryRetrieveStatusDelayTime = 1000;
|
||||
var _retryRetrieveStatusDelay;
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
var _retrieveNetworkStatusDelayTime = 1000;
|
||||
var _retrieveNetworkStatusDelay;
|
||||
|
||||
// ui elements
|
||||
var _element;
|
||||
var _networkSelector;
|
||||
var _apFieldSet;
|
||||
var _clientFieldSet;
|
||||
var _apRadioButton;
|
||||
var _clientRadioButton;
|
||||
var _btnRefresh
|
||||
var _btnConnect;
|
||||
var _btnCreate;
|
||||
var _passwordField;
|
||||
var _passwordLabel;
|
||||
var _clientStateDisplay;
|
||||
var _apModeStateDisplay;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL,panelElement) {
|
||||
//console.log("NetworkPanel:init");
|
||||
|
||||
_form.init(wifiboxURL,wifiboxCGIBinURL,panelElement)
|
||||
|
||||
_api.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
|
||||
_element = panelElement;
|
||||
_apRadioButton = _element.find("#ap");
|
||||
_clientRadioButton = _element.find("#client");
|
||||
_btnRefresh = _element.find("#refreshNetworks");
|
||||
_btnConnect = _element.find("#connectToNetwork");
|
||||
_btnCreate = _element.find("#createAP");
|
||||
_networkSelector = _element.find("#network");
|
||||
_apFieldSet = _element.find("#apSettings");
|
||||
_clientFieldSet = _element.find("#clientSettings");
|
||||
_passwordField = _element.find("#password");
|
||||
_passwordLabel = _element.find("#passwordLabel");
|
||||
_clientStateDisplay = _element.find("#clientModeState");
|
||||
_apModeStateDisplay = _element.find("#apModeState");
|
||||
|
||||
_apRadioButton.parent().on('touchstart mousedown',showAPSettings);
|
||||
_clientRadioButton.parent().on('touchstart mousedown',showClientSettings);
|
||||
_btnRefresh.on('touchstart mousedown',onRefreshClick);
|
||||
_btnConnect.on('touchstart mousedown',_self.connectToNetwork);
|
||||
_btnCreate.on('touchstart mousedown',_self.createAP);
|
||||
_networkSelector.change(networkSelectorChanged);
|
||||
}
|
||||
/*
|
||||
* Handlers
|
||||
*/
|
||||
function showAPSettings() {
|
||||
_apFieldSet.show();
|
||||
_clientFieldSet.hide();
|
||||
};
|
||||
function showClientSettings() {
|
||||
_clientFieldSet.show();
|
||||
_apFieldSet.hide();
|
||||
};
|
||||
function onRefreshClick() {
|
||||
_btnRefresh.attr("disabled", true);
|
||||
_self.refreshNetworks(function() {
|
||||
_btnRefresh.removeAttr("disabled");
|
||||
})
|
||||
}
|
||||
function networkSelectorChanged(e) {
|
||||
var selectedOption = $(this).find("option:selected");
|
||||
_self.selectNetwork(selectedOption.val());
|
||||
};
|
||||
|
||||
this.update = function() {
|
||||
//console.log("NetworkPanel:update");
|
||||
_self.refreshNetworks();
|
||||
_self.retrieveNetworkStatus(false);
|
||||
}
|
||||
this.refreshNetworks = function(completeHandler) {
|
||||
//console.log("NetworkPanel:refreshNetworks");
|
||||
_api.scan(function(data) { // completed
|
||||
//console.log("NetworkPanel:scanned");
|
||||
_networks = {};
|
||||
var foundCurrentNetwork = false;
|
||||
// fill network selector
|
||||
_networkSelector.empty();
|
||||
_networkSelector.append(
|
||||
$("<option></option>").val(NOT_CONNECTED).html(NOT_CONNECTED)
|
||||
);
|
||||
$.each(data.networks, function(index,element) {
|
||||
if(element.ssid == _currentNetwork) {
|
||||
foundCurrentNetwork = true;
|
||||
}
|
||||
_networkSelector.append(
|
||||
$("<option></option>").val(element.ssid).html(element.ssid)
|
||||
);
|
||||
_networks[element.ssid] = element;
|
||||
});
|
||||
if(foundCurrentNetwork) {
|
||||
_networkSelector.val(_currentNetwork);
|
||||
_self.selectNetwork(_currentNetwork);
|
||||
}
|
||||
if(completeHandler) completeHandler();
|
||||
}/*,
|
||||
function() { // failed
|
||||
clearTimeout(_retryRefreshNetworksDelay);
|
||||
_retryRetrieveStatusDelay = setTimeout(function() { _self.refreshNetworks(completeHandler); },_retryDelay); // retry after delay
|
||||
}*/);
|
||||
};
|
||||
|
||||
this.retrieveNetworkStatus = function(connecting) {
|
||||
//console.log("NetworkPanel:retrieveNetworkStatus");
|
||||
_api.status(function(data) {
|
||||
if(data.status === "") {
|
||||
data.status = NetworkAPI.STATUS.CREATED.toString();
|
||||
}
|
||||
if(typeof data.status === 'string') {
|
||||
data.status = parseInt(data.status);
|
||||
}
|
||||
//console.log("NetworkPanel:retrievedStatus status: ",data.status,data.statusMessage);
|
||||
|
||||
// if status changed
|
||||
if(data.status != _currentNetworkStatus) {
|
||||
// Determine which network mode ui to show
|
||||
switch(data.status) {
|
||||
case NetworkAPI.STATUS.NOT_CONNECTED:
|
||||
setNetworkMode(NetworkPanel.NETWORK_MODE.NEITHER);
|
||||
break;
|
||||
case NetworkAPI.STATUS.CONNECTING_FAILED:
|
||||
case NetworkAPI.STATUS.CONNECTING:
|
||||
case NetworkAPI.STATUS.CONNECTED:
|
||||
setNetworkMode(NetworkPanel.NETWORK_MODE.CLIENT);
|
||||
break;
|
||||
case NetworkAPI.STATUS.CREATING:
|
||||
case NetworkAPI.STATUS.CREATED:
|
||||
setNetworkMode(NetworkPanel.NETWORK_MODE.ACCESS_POINT);
|
||||
break;
|
||||
}
|
||||
// update info
|
||||
switch(data.status) {
|
||||
case NetworkAPI.STATUS.CONNECTED:
|
||||
_currentNetwork = data.ssid;
|
||||
_currentLocalIP = data.localip;
|
||||
_self.selectNetwork(data.ssid);
|
||||
break;
|
||||
case NetworkAPI.STATUS.CONNECTING_FAILED:
|
||||
case NetworkAPI.STATUS.CONNECTING:
|
||||
_currentLocalIP = "";
|
||||
break;
|
||||
case NetworkAPI.STATUS.CREATING:
|
||||
case NetworkAPI.STATUS.CREATED:
|
||||
_currentNetwork = undefined;
|
||||
_self.selectNetwork(NOT_CONNECTED);
|
||||
if(data.ssid && data.status == NetworkAPI.STATUS.CREATED) {
|
||||
_currentAP = data.ssid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// update ui
|
||||
updateClientModeUI(data.status,data.statusMessage);
|
||||
updateAPModeUI(data.status,"");
|
||||
}
|
||||
|
||||
// Keep checking for updates?
|
||||
if(connecting) {
|
||||
switch(data.status) {
|
||||
case NetworkAPI.STATUS.CONNECTING:
|
||||
case NetworkAPI.STATUS.CREATING:
|
||||
clearTimeout(_retryRetrieveStatusDelay);
|
||||
_retryRetrieveStatusDelay = setTimeout(function() { _self.retrieveNetworkStatus(connecting); },_retryRetrieveStatusDelayTime); // retry after delay
|
||||
break;
|
||||
}
|
||||
}
|
||||
_currentNetworkStatus = data.status;
|
||||
}, function() {
|
||||
//console.log("NetworkPanel:retrieveStatus failed");
|
||||
clearTimeout(_retryRetrieveStatusDelay);
|
||||
_retryRetrieveStatusDelay = setTimeout(function() { _self.retrieveNetworkStatus(connecting); }, _retryRetrieveStatusDelayTime); // retry after delay
|
||||
});
|
||||
};
|
||||
function setNetworkMode(mode) {
|
||||
//console.log("NetworkPanel:setNetworkMode: ",_networkMode,">",mode);
|
||||
if(mode == _networkMode) return;
|
||||
switch(mode) {
|
||||
case NetworkPanel.NETWORK_MODE.NEITHER:
|
||||
_apFieldSet.show();
|
||||
_clientFieldSet.show();
|
||||
break;
|
||||
case NetworkPanel.NETWORK_MODE.CLIENT:
|
||||
_clientRadioButton.prop('checked',true);
|
||||
_apFieldSet.hide();
|
||||
_clientFieldSet.show();
|
||||
break;
|
||||
case NetworkPanel.NETWORK_MODE.ACCESS_POINT:
|
||||
_apRadioButton.prop('checked',true);
|
||||
_apFieldSet.show();
|
||||
_clientFieldSet.hide();
|
||||
break;
|
||||
}
|
||||
_networkMode = mode;
|
||||
if(_networkModeChangedHandler) _networkModeChangedHandler(_networkMode);
|
||||
}
|
||||
|
||||
this.selectNetwork = function(ssid) {
|
||||
//console.log("NetworkPanel:selectNetwork: ",ssid);
|
||||
if(ssid == "") return;
|
||||
_selectedNetwork = ssid;
|
||||
|
||||
var network = _networks[ssid];
|
||||
if(network === undefined || network.encryption == "none") {
|
||||
_passwordLabel.hide();
|
||||
_passwordField.hide();
|
||||
} else {
|
||||
_passwordLabel.show();
|
||||
_passwordField.show();
|
||||
}
|
||||
_passwordField.val("");
|
||||
};
|
||||
|
||||
function updateClientModeUI(state,statusMessage) {
|
||||
//console.log("NetworkPanel:updateClientModeUI ",state,statusMessage);
|
||||
var msg = "";
|
||||
switch(state) {
|
||||
case NetworkAPI.STATUS.NOT_CONNECTED:
|
||||
case NetworkAPI.STATUS.CREATING:
|
||||
case NetworkAPI.STATUS.CREATED:
|
||||
_btnConnect.removeAttr("disabled");
|
||||
msg = "Not connected";
|
||||
_networkSelector.val(NOT_CONNECTED);
|
||||
break;
|
||||
case NetworkAPI.STATUS.CONNECTED:
|
||||
_btnConnect.removeAttr("disabled");
|
||||
msg = "Connected to: <b>"+_currentNetwork+"</b>.";
|
||||
if(_currentLocalIP != undefined && _currentLocalIP != "") {
|
||||
var a = "<a href='http://"+_currentLocalIP+"' target='_black'>"+_currentLocalIP+"</a>";
|
||||
msg += " (IP: "+a+")";
|
||||
}
|
||||
_networkSelector.val(_currentNetwork);
|
||||
break;
|
||||
case NetworkAPI.STATUS.CONNECTING:
|
||||
_btnConnect.attr("disabled", true);
|
||||
msg = "Connecting... Reconnect by connecting your device to <b>"+_selectedNetwork+"</b> and going to <a href='http://connect.doodle3d.com'>connect.doodle3d.com</a>";
|
||||
break;
|
||||
case NetworkAPI.STATUS.CONNECTING_FAILED:
|
||||
_btnConnect.removeAttr("disabled");
|
||||
msg = statusMessage;
|
||||
break;
|
||||
}
|
||||
//console.log(" client display msg: ",msg);
|
||||
_clientStateDisplay.html(msg);
|
||||
};
|
||||
function updateAPModeUI(state,statusMessage) {
|
||||
var msg = "";
|
||||
switch(state) {
|
||||
case NetworkAPI.STATUS.CONNECTING_FAILED:
|
||||
case NetworkAPI.STATUS.NOT_CONNECTED:
|
||||
case NetworkAPI.STATUS.CONNECTING:
|
||||
case NetworkAPI.STATUS.CONNECTED:
|
||||
_btnCreate.removeAttr("disabled");
|
||||
msg = "Not currently a access point";
|
||||
break;
|
||||
case NetworkAPI.STATUS.CREATED:
|
||||
_btnCreate.removeAttr("disabled");
|
||||
msg = "Is access point: <b>"+_currentAP+"</b>";
|
||||
break;
|
||||
case NetworkAPI.STATUS.CREATING:
|
||||
_btnCreate.attr("disabled", true);
|
||||
msg = "Creating access point... Reconnect by connecting your device to <b>"+_substituted_ssid+"</b> and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>";
|
||||
break;
|
||||
}
|
||||
//console.log(" ap display msg: ",msg);
|
||||
_apModeStateDisplay.html(msg);
|
||||
};
|
||||
|
||||
this.connectToNetwork = function() {
|
||||
//console.log("NetworkPanel:connectToNetwork");
|
||||
if(_selectedNetwork == undefined) return;
|
||||
// save network related settings and on complete, connect to network
|
||||
_form.saveSettings(_form.readForm(),function(validated, data) {
|
||||
if(!validated) return;
|
||||
updateClientModeUI(NetworkAPI.STATUS.CONNECTING,"");
|
||||
_api.associate(_selectedNetwork,_passwordField.val(),true);
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch it's status
|
||||
clearTimeout(_retrieveNetworkStatusDelay);
|
||||
_retrieveNetworkStatusDelay = setTimeout(function() { _self.retrieveNetworkStatus(true); }, _retrieveNetworkStatusDelayTime);
|
||||
});
|
||||
};
|
||||
|
||||
this.createAP = function() {
|
||||
//console.log("createAP");
|
||||
// save network related settings and on complete, create access point
|
||||
_form.saveSettings(_form.readForm(),function(validated, data) {
|
||||
if(!validated) return;
|
||||
_substituted_ssid = data.substituted_ssid;
|
||||
updateAPModeUI(NetworkAPI.STATUS.CREATING,"");
|
||||
_api.openAP();
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch it's status
|
||||
clearTimeout(_retrieveNetworkStatusDelay);
|
||||
_retrieveNetworkStatusDelay = setTimeout(function() { _self.retrieveNetworkStatus(true); }, _retrieveNetworkStatusDelayTime);
|
||||
});
|
||||
};
|
||||
|
||||
this.setNetworkModeChangedHandler = function(handler) {
|
||||
_networkModeChangedHandler = handler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function PrinterPanel() {
|
||||
|
||||
this.printerType;
|
||||
var _api = new PrinterAPI();
|
||||
var _form = new FormPanel();
|
||||
|
||||
// ui elements
|
||||
var _element;
|
||||
var _printerSelector;
|
||||
var _printerSettings;
|
||||
|
||||
var _self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL,panelElement) {
|
||||
|
||||
_form.init(wifiboxURL,wifiboxCGIBinURL,panelElement)
|
||||
_api.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
_element = panelElement;
|
||||
_printerSelector = _element.find("#printerType");
|
||||
_printerSelector.change(_self.printerSelectorChanged);
|
||||
|
||||
// we use readForm to get all the settings we need to
|
||||
// reload after changing printer type
|
||||
_printerSettings = _form.readForm();
|
||||
|
||||
var gcodePanel = _element.find("#gcodePanel");
|
||||
gcodePanel.coolfieldset({collapsed:true});
|
||||
}
|
||||
this.load = function(completeHandler) {
|
||||
|
||||
_api.listAll(function(data) {
|
||||
$.each(data.printers, function(key, value) {
|
||||
// console.log(key,value);
|
||||
$('#printerType').append($('<option>').text(value).attr('value', key));
|
||||
});
|
||||
completeHandler();
|
||||
});
|
||||
}
|
||||
this.printerSelectorChanged = function(e) {
|
||||
_self.printerType = _printerSelector.find("option:selected").val();
|
||||
var settings = {};
|
||||
settings[_printerSelector.attr("name")] = _self.printerType;
|
||||
|
||||
_form.saveSettings(settings,function(validated) {
|
||||
if(!validated) return;
|
||||
_form.loadSettings(_printerSettings,function(settings) {
|
||||
_form.fillForm(settings);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
|
||||
var settings = {};
|
||||
var settingsPopup;
|
||||
//wrapper to prevent scoping issues in showSettings()
|
||||
function openSettingsWindow() {
|
||||
settingsWindow.loadSettings(function() { // reload settings
|
||||
settingsPopup.open();
|
||||
});
|
||||
}
|
||||
|
||||
function SettingsWindow() {
|
||||
|
||||
var _window;
|
||||
var _btnOK;
|
||||
|
||||
var _wifiboxURL;
|
||||
var _restoredStateHideDelayTime = 3000;
|
||||
var _restoredStateHideDelay; // setTimout instance
|
||||
|
||||
// Events
|
||||
SettingsWindow.SETTINGS_LOADED = "settingsLoaded";
|
||||
|
||||
var _form = new FormPanel();
|
||||
var _updatePanel = new UpdatePanel();
|
||||
var _printerPanel = new PrinterPanel();
|
||||
var _networkPanel = new NetworkPanel();
|
||||
var _networkAPI = new NetworkAPI();
|
||||
|
||||
var _restoreStateField;
|
||||
var _initialLogLevel = undefined;
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
|
||||
|
||||
_wifiboxURL = wifiboxURL;
|
||||
|
||||
_window = $("#popupSettings");
|
||||
_btnOK = _window.find(".btnOK");
|
||||
settingsPopup = new Popup($("#popupSettings"), $("#popupMask"));
|
||||
settingsPopup.setEnterEnabled(false);
|
||||
settingsPopup.setAutoCloseEnabled(false);
|
||||
|
||||
_btnOK.on('touchstart mousedown',settingsPopup.commit);
|
||||
$("#popupSettings").bind("onPopupCancel", function() { settingsPopup.close(); } );
|
||||
$("#popupSettings").bind("onPopupCommit", self.submitwindow);
|
||||
|
||||
_networkAPI.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
|
||||
// Load external settings.html into SettingsWindow
|
||||
_window.find("#settingsContainer").load("settings.html", function() {
|
||||
console.log("Settings:finished loading settings.html");
|
||||
|
||||
var formElement = _window.find("form");
|
||||
formElement.submit(function (e) { self.submitwindow(e); });
|
||||
|
||||
_form.init(wifiboxURL,wifiboxCGIBinURL,formElement);
|
||||
|
||||
// printer panel
|
||||
var printerPanelElement = formElement.find("#printerPanel");
|
||||
_printerPanel.init(wifiboxURL,wifiboxCGIBinURL,printerPanelElement);
|
||||
|
||||
// Load printer types list
|
||||
// First, because after the settings are loaded the printer type need to be selected
|
||||
_printerPanel.load(function() {
|
||||
|
||||
_restoreStateField = formElement.find("#restoreState");
|
||||
self.btnRestoreSettings = formElement.find("#restoreSettings");
|
||||
self.btnRestoreSettings.on('touchstart mousedown',self.resetSettings);
|
||||
|
||||
// network panel
|
||||
var $networkPanelElement = formElement.find("#networkPanel");
|
||||
_networkPanel.init(wifiboxURL,wifiboxCGIBinURL,$networkPanelElement);
|
||||
|
||||
|
||||
// update panel
|
||||
var updatePanelElement = formElement.find("#updatePanel");
|
||||
_updatePanel.init(wifiboxURL,updatePanelElement);
|
||||
_networkPanel.setNetworkModeChangedHandler(function(networkMode) {
|
||||
var inAccessPointMode = (networkMode == NetworkPanel.NETWORK_MODE.ACCESS_POINT);
|
||||
_updatePanel.setInAccessPointMode(inAccessPointMode);
|
||||
});
|
||||
|
||||
self.loadSettings();
|
||||
|
||||
});
|
||||
}); //this.window.find
|
||||
}; //this.init
|
||||
|
||||
this.openSettings = function() {
|
||||
self.loadSettings(function() { // reload settings
|
||||
settingsPopup.open();
|
||||
});
|
||||
};
|
||||
|
||||
// this.closeSettings = function(complete) {
|
||||
// settingsPopup.close(complete);
|
||||
// };
|
||||
|
||||
this.submitwindow = function(e) {
|
||||
_btnOK.attr("disabled",true);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var newSettings = _form.readForm();
|
||||
_form.saveSettings(newSettings,function(validated, data){
|
||||
if(validated) {
|
||||
settings = newSettings; // store new settings in global settings
|
||||
settingsPopup.close();
|
||||
self.signin();
|
||||
}
|
||||
|
||||
//FIXME: instead of this rather ugly call, implement events for changes to settings so we can keep code decoupled
|
||||
redrawDoodle(false);
|
||||
|
||||
_btnOK.removeAttr("disabled");
|
||||
});
|
||||
};
|
||||
|
||||
this.loadSettings = function(complete) {
|
||||
_form.loadAllSettings(function(loadedSettings){
|
||||
console.log("Settings:loaded settings: ",loadedSettings);
|
||||
settings = loadedSettings;
|
||||
|
||||
//only set the initial level once, to make behaviour of restart warning as correctly as possible
|
||||
if (_initialLogLevel == undefined)
|
||||
_initialLogLevel = loadedSettings['system.log.level'];
|
||||
updateLogLevelWarningsVisibility();
|
||||
|
||||
_form.fillForm(settings);
|
||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||
if(complete) complete();
|
||||
});
|
||||
_networkPanel.update();
|
||||
};
|
||||
|
||||
this.resetSettings = function() {
|
||||
console.log("resetSettings");
|
||||
self.btnRestoreSettings.attr("disabled", true);
|
||||
clearTimeout(_restoredStateHideDelay);
|
||||
self.setRestoreState("Restoring...");
|
||||
_form.resetAllSettings(function(restoredSettings) {
|
||||
//console.log(" settings: ",restoredSettings);
|
||||
settings = restoredSettings;
|
||||
_form.fillForm(restoredSettings);
|
||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||
|
||||
self.btnRestoreSettings.removeAttr("disabled");
|
||||
self.setRestoreState("Settings restored");
|
||||
// auto hide status
|
||||
clearTimeout(_restoredStateHideDelay);
|
||||
_restoredStateHideDelay = setTimeout(function() { self.setRestoreState(""); },_restoredStateHideDelayTime);
|
||||
});
|
||||
};
|
||||
|
||||
this.setRestoreState = function(text) {
|
||||
_restoreStateField.html(text);
|
||||
};
|
||||
|
||||
this.signin = function() {
|
||||
_networkAPI.signin();
|
||||
};
|
||||
|
||||
this.downloadlogs = function() {
|
||||
window.location.href = _wifiboxURL + "/info/logfiles";
|
||||
};
|
||||
|
||||
this.downloadGcode = function() {
|
||||
var gcode = generate_gcode();
|
||||
if (gcode!=undefined) {
|
||||
var blob = new Blob([gcode.join("\n")], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, "doodle3d.gcode");
|
||||
}
|
||||
};
|
||||
|
||||
this.downloadSvg = function() {
|
||||
var svg = saveToSvg();
|
||||
if (svg!=undefined) {
|
||||
var blob = new Blob([svg], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, "doodle3d.svg");
|
||||
}
|
||||
};
|
||||
|
||||
this.openFileManager = function() {
|
||||
location.href = "filemanager/"+location.search;
|
||||
}
|
||||
|
||||
this.logLevelChanged = function() {
|
||||
updateLogLevelWarningsVisibility();
|
||||
}
|
||||
|
||||
|
||||
/***** LOCAL FUNCTIONS *****/
|
||||
|
||||
function updateLogLevelWarningsVisibility() {
|
||||
var showHideAnimDuration = 100;
|
||||
newLevel = $('#logLevel').val();
|
||||
if (_initialLogLevel != newLevel) {
|
||||
$('#logging-restart-warning').show(showHideAnimDuration);
|
||||
} else {
|
||||
$('#logging-restart-warning').hide(showHideAnimDuration);
|
||||
}
|
||||
|
||||
switch (newLevel) {
|
||||
case "verbose": case "bulk":
|
||||
$('#logging-verbose-warning').show(showHideAnimDuration);
|
||||
break;
|
||||
default:
|
||||
$('#logging-verbose-warning').hide(showHideAnimDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
*
|
||||
*
|
||||
* FROM DOODLE3D.INI
|
||||
*
|
||||
*/
|
||||
|
||||
//TODO: find all references to these variables, replace them and finally remove these.
|
||||
var objectHeight = 20;
|
||||
var layerHeight = .2;
|
||||
//var wallThickness = .5;
|
||||
//var hop = 0;
|
||||
//var speed = 70;
|
||||
//var travelSpeed = 200;
|
||||
var enableTraveling = true;
|
||||
//var filamentThickness = 2.89;
|
||||
var minScale = .3;
|
||||
var maxScale = 1;
|
||||
var shape = "%";
|
||||
var twists = 0;
|
||||
//var useSubLayers = true;
|
||||
//var debug = false; // debug moved to main.js
|
||||
var loglevel = 2;
|
||||
//var zOffset = 0;
|
||||
var serverport = 8888;
|
||||
var autoLoadImage = "hand.txt";
|
||||
var loadOffset = [0, 0]; // x en y ?
|
||||
var showWarmUp = true;
|
||||
var loopAlways = false;
|
||||
var firstLayerSlow = true;
|
||||
var useSubpathColors = false;
|
||||
var autoWarmUp = true;
|
||||
//var maxObjectHeight = 150;
|
||||
var maxScaleDifference = .1;
|
||||
var frameRate = 60;
|
||||
var quitOnEscape = true;
|
||||
var screenToMillimeterScale = .3; // 0.3
|
||||
//var targetTemperature = 220;
|
||||
//var simplifyiterations = 10;
|
||||
//var simplifyminNumPoints = 15;
|
||||
//var simplifyminDistance = 3;
|
||||
//var retractionspeed = 50;
|
||||
//var retractionminDistance = 5;
|
||||
//var retractionamount = 3;
|
||||
var sideis3D = true;
|
||||
var sidevisible = true;
|
||||
var sidebounds = [900, 210, 131, 390];
|
||||
var sideborder = [880, 169, 2, 471];
|
||||
var windowbounds = [0, 0, 800, 500];
|
||||
var windowcenter = true;
|
||||
var windowfullscreen = false;
|
||||
var autoWarmUpCommand = "M104 S230";
|
||||
//var checkTemperatureInterval = 3;
|
||||
var autoWarmUpDelay = 3;
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
function UpdatePanel() {
|
||||
var _form = new FormPanel();
|
||||
|
||||
this.wifiboxURL;
|
||||
this.element;
|
||||
|
||||
this.statusCheckInterval = 1000;
|
||||
this.statusCheckDelayer; // setTimout instance
|
||||
this.installedDelay = 90*1000; // Since we can't retrieve status during installation we show the installed text after a fixed delay
|
||||
this.installedDelayer; // setTimout instance
|
||||
this.retryDelay = 1000;
|
||||
this.retryDelayer; // setTimout instance
|
||||
//this.timeoutTime = 3000;
|
||||
|
||||
this.canUpdate = false;
|
||||
this.currentVersion = "";
|
||||
this.newestVersion;
|
||||
this.currentReleaseDate;
|
||||
this.newestReleaseDate;
|
||||
this.progress;
|
||||
this.imageSize;
|
||||
var _inAccessPointMode;
|
||||
|
||||
// states from api, see Doodle3D firmware src/script/d3d-updater.lua
|
||||
UpdatePanel.NONE = 1; // default state
|
||||
UpdatePanel.DOWNLOADING = 2;
|
||||
UpdatePanel.DOWNLOAD_FAILED = 3;
|
||||
UpdatePanel.IMAGE_READY = 4; // download successful and checked
|
||||
UpdatePanel.INSTALLING = 5;
|
||||
UpdatePanel.INSTALLED = 6;
|
||||
UpdatePanel.INSTALL_FAILED = 7;
|
||||
|
||||
this.state; // update state from api
|
||||
this.stateText = ""; // update state text from api
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function(wifiboxURL,updatePanelElement) {
|
||||
_form.init(wifiboxURL,wifiboxURL,updatePanelElement);
|
||||
|
||||
this.wifiboxURL = wifiboxURL;
|
||||
|
||||
this.element = updatePanelElement;
|
||||
this.retainCheckbox = this.element.find("#retainConfiguration");
|
||||
this.includeBetasCheckbox = this.element.find("#includeBetas");
|
||||
this.btnUpdate = this.element.find("#update");
|
||||
this.statusDisplay = this.element.find("#updateState");
|
||||
this.infoDisplay = this.element.find("#updateInfo");
|
||||
|
||||
this.retainCheckbox.change(this.retainChanged);
|
||||
this.includeBetasCheckbox.change(this.includeBetasChanged);
|
||||
this.btnUpdate.click(this.update);
|
||||
|
||||
this.checkStatus(false);
|
||||
}
|
||||
|
||||
this.retainChanged = function(e) {
|
||||
//console.log("UpdatePanel:retainChanged");
|
||||
//this call ensures that the update button gets enabled if (!retainChanged && !canUpdate)
|
||||
self.setState(self.state,true);
|
||||
}
|
||||
|
||||
this.includeBetasChanged = function() {
|
||||
//console.log("UpdatePanel:includeBetasChanged");
|
||||
_form.saveSettings(_form.readForm(),function(validated, data) {
|
||||
if(validated) self.checkStatus(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.update = function() {
|
||||
console.log("UpdatePanel:update");
|
||||
self.downloadUpdate();
|
||||
}
|
||||
|
||||
this.downloadUpdate = function() {
|
||||
console.log("UpdatePanel:downloadUpdate");
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/update/download",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
success: function(response){
|
||||
console.log("UpdatePanel:downloadUpdate response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("UpdatePanel:downloadUpdate: failed");
|
||||
});
|
||||
self.setState(UpdatePanel.DOWNLOADING);
|
||||
self.startCheckingStatus();
|
||||
}
|
||||
|
||||
this.installUpdate = function() {
|
||||
console.log("UpdatePanel:installUpdate");
|
||||
|
||||
// should personal sketches and settings be retained over update?
|
||||
var retain = self.retainCheckbox.prop('checked');
|
||||
console.log(" retain: ",retain);
|
||||
|
||||
self.stopCheckingStatus();
|
||||
postData = {no_retain:!retain}
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/update/install",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
success: function(response){
|
||||
console.log("UpdatePanel:installUpdate response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("UpdatePanel:installUpdate: no respons (there shouldn't be)");
|
||||
});
|
||||
self.setState(UpdatePanel.INSTALLING);
|
||||
|
||||
clearTimeout(self.installedDelayer);
|
||||
self.installedDelayer = setTimeout(function() { self.setState(UpdatePanel.INSTALLED) },self.installedDelay);
|
||||
}
|
||||
|
||||
|
||||
this.startCheckingStatus = function() {
|
||||
clearTimeout(self.statusCheckDelayer);
|
||||
clearTimeout(self.retryDelayer);
|
||||
self.statusCheckDelayer = setTimeout(function() { self.checkStatus(true) },self.statusCheckInterval);
|
||||
}
|
||||
|
||||
this.stopCheckingStatus = function() {
|
||||
clearTimeout(self.statusCheckDelayer);
|
||||
clearTimeout(self.retryDelayer);
|
||||
}
|
||||
|
||||
this.checkStatus = function(keepChecking) {
|
||||
if (!communicateWithWifibox) return;
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/update/status",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
//timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("UpdatePanel:checkStatus response: ",response);
|
||||
|
||||
// Keep checking ?
|
||||
if(keepChecking) {
|
||||
switch(self.state){
|
||||
case UpdatePanel.DOWNLOADING:
|
||||
case UpdatePanel.INSTALLING:
|
||||
clearTimeout(self.statusCheckDelayer);
|
||||
self.statusCheckDelayer = setTimeout(function() { self.checkStatus(keepChecking) },self.statusCheckInterval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(response.status != "error") {
|
||||
var data = response.data;
|
||||
self.handleStatusData(data);
|
||||
} else {
|
||||
console.log("API update/status call returned an error: '" + response.msg + "'");
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
//console.log("UpdatePanel:checkStatus: failed");
|
||||
if(keepChecking) {
|
||||
clearTimeout(self.retryDelayer);
|
||||
self.retryDelayer = setTimeout(function() { self.checkStatus(keepChecking) },self.retryDelay); // retry after delay
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.handleStatusData = function(data) {
|
||||
//console.log("UpdatePanel:handleStatusData");
|
||||
//status texts and button state might have to be updated if the newest version changes (e.g., after (un)ticking include betas checkbox)
|
||||
var refreshUI = (self.newestVersion != data.newest_version);
|
||||
|
||||
self.canUpdate = data.can_update;
|
||||
|
||||
if(self.currentVersion != data.current_version || self.newestVersion != data.newest_version) {
|
||||
self.currentVersion = data.current_version;
|
||||
self.newestVersion = data.newest_version;
|
||||
self.currentReleaseDate = data.current_release_date; // not always available (for older versions)
|
||||
self.newestReleaseDate = data.newest_release_date; // not always available (for older versions)
|
||||
self.updateInfoDisplay();
|
||||
}
|
||||
|
||||
self.stateText = data.state_text;
|
||||
self.progress = data.progress; // not always available
|
||||
self.imageSize = data.image_size; // not always available
|
||||
|
||||
self.setState(data.state_code, refreshUI);
|
||||
|
||||
switch(this.state){
|
||||
case UpdatePanel.IMAGE_READY:
|
||||
self.installUpdate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState = function(newState,refresh) {
|
||||
//console.log("UpdatePanel:setState");
|
||||
if(!refresh && this.state == newState) return;
|
||||
console.log("UpdatePanel:setState: " + this.state + " > " + newState + "(" + this.stateText + ") (in Access Point Mode: " + _inAccessPointMode + ") (newestVersion: " + self.newestVersion + ") (refresh: " + refresh + ")");
|
||||
this.state = newState;
|
||||
|
||||
// should personal sketches and settings be retained over update?
|
||||
var retain = self.retainCheckbox.prop('checked');
|
||||
//console.log(" retain", retain);
|
||||
|
||||
// download button
|
||||
// if there isn't newestVersion data something went wrong,
|
||||
// probably accessing the internet
|
||||
//console.log(" self.newestVersion: ",self.newestVersion);
|
||||
if(self.newestVersion != undefined) {
|
||||
//console.log(" this.state: ",this.state);
|
||||
switch(this.state){
|
||||
case UpdatePanel.NONE:
|
||||
case UpdatePanel.DOWNLOAD_FAILED:
|
||||
case UpdatePanel.INSTALL_FAILED:
|
||||
//console.log(" self.canUpdate: ",self.canUpdate);
|
||||
if(self.canUpdate || !retain) {
|
||||
self.btnUpdate.removeAttr("disabled");
|
||||
} else {
|
||||
self.btnUpdate.attr("disabled", true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
self.btnUpdate.attr("disabled", true);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
self.btnUpdate.attr("disabled", true);
|
||||
}
|
||||
this.updateStatusDisplay();
|
||||
}
|
||||
|
||||
this.updateStatusDisplay = function() {
|
||||
var text = "";
|
||||
if(self.newestVersion != undefined) {
|
||||
switch(this.state){
|
||||
case UpdatePanel.NONE:
|
||||
if(self.canUpdate) {
|
||||
var currIsBeta = self.versionIsBeta(self.currentVersion);
|
||||
var newIsBeta = self.versionIsBeta(self.newestVersion);
|
||||
var relIsNewer = (self.newestReleaseDate && self.currentReleaseDate) ? (self.newestReleaseDate - self.currentReleaseDate > 0) : true;
|
||||
|
||||
if (!newIsBeta) {
|
||||
if (relIsNewer) text = "Update available.";
|
||||
else text = "You can switch back to the latest stable release."; //this case is always a beta->stable 'downgrade'
|
||||
} else {
|
||||
//NOTE: actually, an older beta will never be presented as update by the API
|
||||
var prefixText = currIsBeta ? "A" : (relIsNewer ? "A newer" : "An older");
|
||||
text = prefixText + " beta release is available.";
|
||||
}
|
||||
} else {
|
||||
text = "You're up to date.";
|
||||
}
|
||||
break;
|
||||
case UpdatePanel.DOWNLOADING:
|
||||
text = "Downloading update...";
|
||||
break;
|
||||
case UpdatePanel.DOWNLOAD_FAILED:
|
||||
text = "Downloading update failed.";
|
||||
break;
|
||||
case UpdatePanel.IMAGE_READY:
|
||||
text = "Update downloaded.";
|
||||
break;
|
||||
case UpdatePanel.INSTALLING:
|
||||
text = "Installing update... (will take a minute)";
|
||||
break;
|
||||
case UpdatePanel.INSTALLED:
|
||||
//text = "Update complete, please reconnect by connecting your device to the access point of your WiFi box and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>";
|
||||
text = "Update complete, please <a href='javascript:location.reload(true);'>refresh Page</a>.";
|
||||
break;
|
||||
case UpdatePanel.INSTALL_FAILED:
|
||||
text = "Installing update failed.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(_inAccessPointMode) {
|
||||
text = "Can't access internet in access point mode.";
|
||||
} else {
|
||||
text = "Can't access internet.";
|
||||
}
|
||||
}
|
||||
this.statusDisplay.html(text);
|
||||
}
|
||||
|
||||
this.updateInfoDisplay = function() {
|
||||
var html = 'Current version: ' + self.currentVersion;
|
||||
if (self.currentReleaseDate) html += '; released: ' + self.formatDate(self.currentReleaseDate);
|
||||
html += ' (<a target="d3d-curr-relnotes" href="ReleaseNotes.html">release notes</a>).';
|
||||
|
||||
if(self.canUpdate) {
|
||||
html += '<br/>Latest version: ' + self.newestVersion;
|
||||
if (self.newestReleaseDate) html += '; released: ' + self.formatDate(self.newestReleaseDate);
|
||||
html += ' (<a target="d3d-new-relnotes" href="http://doodle3d.com/updates/images/ReleaseNotes.md">release notes</a>).';
|
||||
}
|
||||
self.infoDisplay.html(html);
|
||||
}
|
||||
|
||||
|
||||
this.setInAccessPointMode = function(inAccessPointMode) {
|
||||
_inAccessPointMode = inAccessPointMode;
|
||||
self.updateStatusDisplay();
|
||||
}
|
||||
|
||||
this.formatDate = function(ts) {
|
||||
if (!ts || ts.length != 8 || !/^[0-9]+$/.test(ts)) return null;
|
||||
var fields = [ ts.substr(0, 4), ts.substr(4, 2), ts.substr(6, 2) ];
|
||||
if (!fields || fields.length != 3 || fields[1] > 12) return null;
|
||||
|
||||
var abbrMonths = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
|
||||
return abbrMonths[fields[1] - 1] + " " + fields[2] + ", " + fields[0];
|
||||
}
|
||||
|
||||
this.versionIsBeta = function(version) {
|
||||
return version ? /.*-.*/g.test(version) : null;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var sidebarLeft;
|
||||
var sidebarRight;
|
||||
|
||||
|
@ -5,13 +13,13 @@ function initSidebars() {
|
|||
console.log("f:initSidebars()");
|
||||
|
||||
sidebarLeft = new SideBar();
|
||||
sidebarLeft.init(".leftpanel", "hideleft", function() {
|
||||
$(".leftpanel").show();
|
||||
sidebarLeft.init("#leftpanel", "hideleft", function() {
|
||||
$("#leftpanel").show();
|
||||
});
|
||||
|
||||
sidebarRight = new SideBar();
|
||||
sidebarRight.init(".rightpanel", "hideright", function() {
|
||||
$(".rightpanel").show();
|
||||
sidebarRight.init("#rightpanel", "hideright", function() {
|
||||
$("#rightpanel").show();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
var curSketch = 0;
|
||||
var sketches = []; //contains fileIDs
|
||||
|
||||
function previousSketch(e) {
|
||||
loadSketch(curSketch-1);
|
||||
}
|
||||
|
||||
function nextSketch(e) {
|
||||
loadSketch(curSketch+1);
|
||||
}
|
||||
|
||||
function newSketch(e) {
|
||||
clearDoodle();
|
||||
curSketch = sketches.length; //index of the last item + 1
|
||||
updateSketchButtonStates();
|
||||
}
|
||||
|
||||
function listSketches() {
|
||||
console.log('listSketches')
|
||||
$.get(wifiboxURL + "/sketch/list", function(data) {
|
||||
if (data.status=='success') {
|
||||
sketches = data.data.list;
|
||||
curSketch = sketches.length-1;
|
||||
setSketchModified(false);
|
||||
updateSketchButtonStates();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setSketchModified(_isModified) {
|
||||
isModified = _isModified;
|
||||
updateSketchButtonStates();
|
||||
}
|
||||
|
||||
function updateSketchButtonStates() {
|
||||
console.log('sketch: isModified: ' + isModified + ', curSketch: ' + curSketch + ', sketches.length: ' + sketches.length);
|
||||
|
||||
if (isModified) {
|
||||
btnSave.enable();
|
||||
}
|
||||
else {
|
||||
btnSave.disable();
|
||||
}
|
||||
|
||||
if (curSketch<sketches.length-1) {
|
||||
btnNext.enable();
|
||||
} else {
|
||||
btnNext.disable();
|
||||
}
|
||||
|
||||
if (curSketch>0) {
|
||||
btnPrevious.enable();
|
||||
} else {
|
||||
btnPrevious.disable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadSketch(_curSketch) {
|
||||
curSketch = _curSketch;
|
||||
|
||||
if (curSketch<0) curSketch=0;
|
||||
if (curSketch>sketches.length-1) curSketch=sketches.length-1;
|
||||
|
||||
var id = sketches[curSketch];
|
||||
|
||||
console.log('sketch: loadSketch curSketch:' + curSketch + ', id: ' + id);
|
||||
|
||||
$.get(wifiboxURL + "/sketch", {id:id}, function(response) {
|
||||
if (response.status=='success') {
|
||||
console.log('sketch: loaded',response);
|
||||
var svgData = response.data.data;
|
||||
loadFromSvg(svgData);
|
||||
setSketchModified(false);
|
||||
} else {
|
||||
console.log('error loading sketch: ',response);
|
||||
listSketches();
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function saveSketch() {
|
||||
console.log("sketch: saveSketch");
|
||||
var svgData = saveToSvg();
|
||||
|
||||
$.post(wifiboxURL + "/sketch", {data: svgData}, function(response) {
|
||||
console.log("sketch: saveSketch: response",response);
|
||||
listSketches();
|
||||
})
|
||||
|
||||
}
|
32
js/utils.js
|
@ -1,3 +1,10 @@
|
|||
/*
|
||||
* This file is part of the Doodle3D project (http://doodle3d.com).
|
||||
*
|
||||
* Copyright (c) 2013, Doodle3D
|
||||
* This software is licensed under the terms of the GNU GPL v2 or later.
|
||||
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
|
||||
*/
|
||||
|
||||
// http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery
|
||||
function getURLParameter(name) {
|
||||
|
@ -5,3 +12,28 @@ function getURLParameter(name) {
|
|||
(new RegExp('[&?]'+name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
|
||||
);
|
||||
}
|
||||
|
||||
// returns true for all smartphones and tablets
|
||||
function isMobileDevice() {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Mobile/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
// returns true for smartphones (Android will be a bit dodgy (tablet or phone, all depends on pixels vs devicePixelRatio...)
|
||||
function isSmartphone() {
|
||||
var returnBool = false;
|
||||
if( /Android/i.test(navigator.userAgent) && window.devicePixelRatio > 1) {
|
||||
var w = $(window).width() / window.devicePixelRatio;
|
||||
console.log("Android device >> ratio'd width: " + w);
|
||||
if (w < 480) {
|
||||
returnBool = true;
|
||||
}
|
||||
} else {
|
||||
returnBool = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini|Windows Mobile/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
return returnBool;
|
||||
}
|
||||
|
||||
function distance(x1, y1, x2, y2) {
|
||||
return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var VERTICALSHAPE;
|
||||
|
||||
var verticalShapes = {
|
||||
"NONE": 'none',
|
||||
"DIVERGING": 'diverging',
|
||||
|
@ -6,36 +7,15 @@ var verticalShapes = {
|
|||
"SINUS": 'sinus'
|
||||
};
|
||||
|
||||
function initVerticalShapes() {
|
||||
// TODO give these vertical shapes a better spot
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
$(".verticalShapes, .straight").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("diverging");
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .diverging").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("diverging");
|
||||
VERTICALSHAPE = verticalShapes.DIVERGING;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .converging").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("converging");
|
||||
VERTICALSHAPE = verticalShapes.CONVERGING;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .sinus").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("sinus");
|
||||
VERTICALSHAPE = verticalShapes.SINUS;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
function setVerticalShape(s) {
|
||||
VERTICALSHAPE = s;
|
||||
redrawRenderedPreview();
|
||||
}
|
||||
|
||||
function initVerticalShapes() {
|
||||
resetVerticalShapes();
|
||||
}
|
||||
|
||||
function resetVerticalShapes() {
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
setVerticalShape(verticalShapes.NONE);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#page404 {
|
||||
#message404 {
|
||||
font-family: Helvetica,Arial,"Nimbus Sans L",sans-serif;
|
||||
font-size: 16px;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 200px;
|
||||
width: 30em;
|
||||
margin: -85px 0px 0px -16em;
|
||||
|
||||
background-color: #FCFCFC;
|
||||
padding: 0px 1em;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 485px) {
|
||||
#page404 {
|
||||
overflow-y: auto;
|
||||
#message404 {
|
||||
position: relative;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
margin: 10% 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
p, ul {
|
||||
margin: 1em;
|
||||
}
|
||||
}
|
||||
#landscape {
|
||||
box-shadow: none;
|
||||
.bgContainer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
less/base.less
|
@ -1,113 +1,73 @@
|
|||
/*
|
||||
|
||||
GLOBAL CONTAINER
|
||||
|
||||
*/
|
||||
@import "config.less";
|
||||
|
||||
|
||||
body {
|
||||
background-color: #fcfcfc;
|
||||
-moz-user-select: none; /* disable cut copy paste */
|
||||
-webkit-user-select: none; /* disable cut copy paste */
|
||||
user-select: none; /* disable cut copy paste */
|
||||
overflow:hidden; /* This chops off any overhanging divs */
|
||||
}
|
||||
img {
|
||||
z-index: 5;
|
||||
/*pointer-events:none;*/
|
||||
/*-webkit-touch-callout: none; *//*disable callout, image save panel */
|
||||
/*-webkit-tap-highlight-color: transparent; *//* "turn off" link highlight */
|
||||
}
|
||||
/* http://stackoverflow.com/questions/5348092/prevent-default-press-but-not-default-drag-in-ios-mobilesafari */
|
||||
.btn {
|
||||
background-repeat: no-repeat;
|
||||
/* -webkit-user-select: none;*/
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@import "buttons.less";
|
||||
@import "popup.less";
|
||||
|
||||
#landscape {
|
||||
position:absolute;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
max-width: 1024px;
|
||||
max-height: 768px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
margin: 0px auto;
|
||||
outline: 2px solid #5e8c71;
|
||||
box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/*overflow: hidden;*/
|
||||
margin: 0 auto;
|
||||
|
||||
// solution from: http://stackoverflow.com/questions/14085822/css-firefox-box-shadow-and-outline
|
||||
box-shadow: 0 0 0 2px #5e8c71,
|
||||
0 0 8px 4px rgba(8, 8, 8, 0.25);
|
||||
}
|
||||
|
||||
#portrait {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bgContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bgTop, .bgMiddle, .bgBottom {
|
||||
#bgTop, #bgMiddle, #bgBottom {
|
||||
opacity: 1.0;
|
||||
transition: opacity .35s linear;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
z-index: -5;
|
||||
//z-index: -5;
|
||||
}
|
||||
.bgTop {
|
||||
#bgTop {
|
||||
top: 0px;
|
||||
}
|
||||
.bgMiddle {
|
||||
#bgMiddle {
|
||||
top: 30%;
|
||||
}
|
||||
.bgBottom {
|
||||
#bgBottom {
|
||||
bottom: 0px;
|
||||
}
|
||||
//.rightpanel, .leftpanel {
|
||||
// img {
|
||||
// cursor: pointer;
|
||||
// }
|
||||
//}
|
||||
@media only screen and (max-height: 700px) {
|
||||
#bgMiddle {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CENTER PANEL
|
||||
|
||||
*/
|
||||
@import "base_centerpanel.less";
|
||||
|
||||
/*
|
||||
|
||||
LEFT PANEL
|
||||
|
||||
*/
|
||||
@import "base_leftpanel.less";
|
||||
|
||||
/*
|
||||
|
||||
RIGHT PANEL
|
||||
|
||||
*/
|
||||
@import "base_rightpanel.less";
|
||||
|
||||
|
||||
/*
|
||||
under all the above styles w.r.t. the cascading effect
|
||||
*/
|
||||
.disabled {
|
||||
opacity: 0.3;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#btnStop.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
REST
|
||||
|
||||
*/
|
||||
/* CLEARFIX */
|
||||
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
|
||||
|
|
|
@ -1,58 +1,151 @@
|
|||
// CENTER PANEL
|
||||
.centerpanel {
|
||||
#centerpanel {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -33%;
|
||||
width: 66%;
|
||||
margin-left: -@center-panel-width/2;
|
||||
width: @center-panel-width;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
padding-top: 1%;
|
||||
}
|
||||
|
||||
#logopanel {
|
||||
height: 15%;
|
||||
text-align: center;
|
||||
width: 40%;
|
||||
margin-left: 30%;
|
||||
cursor: pointer;
|
||||
|
||||
// top panel
|
||||
@import "base_centerpanel_logo.less";
|
||||
img#pencil {
|
||||
margin-top: 2%;
|
||||
max-width: 50%;
|
||||
max-height: 50%;
|
||||
}
|
||||
|
||||
// draw area stuff (plus up/down/left/right buttons)
|
||||
@import "base_centerpanel_drawarea.less";
|
||||
img#logo {
|
||||
max-width: 90%;
|
||||
margin-bottom: 2%;
|
||||
max-height: 45%;
|
||||
}
|
||||
}
|
||||
|
||||
// DRAW AREA
|
||||
#drawareacontainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 79%;
|
||||
background-color: #fff;
|
||||
border: 3px solid black;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
margin-top: 1%;
|
||||
}
|
||||
|
||||
#canvasContainers {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mycanvasContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 78%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#mycanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-right: 2px solid #333;
|
||||
}
|
||||
|
||||
#previewContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 22%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#preview {
|
||||
min-width: 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#preview_tmp {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
HEIGHT-related RESPONSIVE STUFF
|
||||
*/
|
||||
@media screen and (max-height: 700px) {
|
||||
.logopanel {
|
||||
height: 22%;
|
||||
}
|
||||
.doodlecontainer {
|
||||
height: 68%;
|
||||
}
|
||||
.d3dlogo {
|
||||
top: 25%;
|
||||
max-width: 399px;
|
||||
height: 74px;
|
||||
background-image: url('../img/logo/logo_small.png');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 655px) {
|
||||
.bgMiddle { opacity: 0; }
|
||||
|
||||
#logopanel {
|
||||
height: 10%;
|
||||
|
||||
img#logo {
|
||||
margin-top: 1%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
img#pencil {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#drawareacontainer {
|
||||
height: 83%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 525px) {
|
||||
.d3dlogo {
|
||||
top: 20%;
|
||||
height: 57px;
|
||||
max-width: 307px;
|
||||
background-image: url('../img/logo/logo_smaller.png');
|
||||
// max-width: 399px;
|
||||
// background-image: url('../img/logo/logo_smaller_wide.png');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 375px) {
|
||||
.d3dlogo {
|
||||
height: 40px;
|
||||
max-width: 216px;
|
||||
background-image: url('../img/logo/logo_smallest.png');
|
||||
// max-width: 399px;
|
||||
// background-image: url('../img/logo/logo_smallest_wide.png');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#mycanvas {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
#imgGuide {
|
||||
// z-index: -1000;
|
||||
// position: absolute;
|
||||
// -webkit-filter: contrast(400%);
|
||||
//-webkit-filter: brightness(100%);
|
||||
// opacity: 50%;
|
||||
opacity: 0.4;
|
||||
filter: alpha(opacity=40);
|
||||
pointer-events:none;
|
||||
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
height: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
// import vertical shapes additions
|
||||
@import "verticalshapes.less";
|
||||
|
||||
// DRAW AREA
|
||||
.drawareacontainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 65%;
|
||||
background-color: #fff;
|
||||
border: 4px solid #000;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#canvasContainers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mycanvasContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 78%;
|
||||
height: 100%;
|
||||
}
|
||||
#mycanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-right: 2px solid #333;
|
||||
}
|
||||
|
||||
#previewContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 22%;
|
||||
// max-width: 150px;
|
||||
height: 100%;
|
||||
}
|
||||
#preview {
|
||||
min-width: 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* DEBUG THING */
|
||||
#preview_tmp {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 500;
|
||||
border: 1px solid #f80;
|
||||
display: none;
|
||||
}
|
||||
.bottompanel {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
/*
|
||||
DOODLE UP/DOWN/LEFT/RIGHT buttons
|
||||
*/
|
||||
.manipulationBtns {
|
||||
margin: 2px 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-width: 340px;
|
||||
max-height: 70px;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.manipulationBtn {
|
||||
width: 45%;
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#btnsUpDown {
|
||||
float: left;
|
||||
width: 45%;
|
||||
}
|
||||
#btnsUpDown > div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnsTurnLeftRight {
|
||||
float: right;
|
||||
width: 45%;
|
||||
}
|
||||
#btnsTurnLeftRight >div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnMoveUp {
|
||||
max-width: 65px;
|
||||
}
|
||||
|
||||
#btnMoveDown {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
#btnTwistLeft {
|
||||
max-width: 59px;
|
||||
}
|
||||
|
||||
#btnTwistRight {
|
||||
max-width: 64px;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
.logopanel {
|
||||
height: 25%;
|
||||
}
|
||||
.d3dlogo {
|
||||
position: relative;
|
||||
top: 15%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px auto;
|
||||
max-width: 399px;
|
||||
height: 139px;
|
||||
background: url('../img/logo/logo_full.png') no-repeat center center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1,42 +1,8 @@
|
|||
// LEFT PANEL
|
||||
.leftpanel {
|
||||
#leftpanel {
|
||||
position: absolute;
|
||||
width: 17%;
|
||||
/* background-color: rgba(67, 204, 67, 0.4);*/
|
||||
width: @left-panel-width;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
.btnNew {
|
||||
margin: 5% 0% 1% 5%;
|
||||
width: 100%;
|
||||
max-width: 180px;
|
||||
height: auto;
|
||||
}
|
||||
.btnsPrevNext {
|
||||
margin: 1% 7%;
|
||||
max-width: 160px;
|
||||
}
|
||||
.btnPrevious {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
}
|
||||
.btnNext {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
.btnSave {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
.btnOops {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
|
|