Version 1.2

This commit is contained in:
Mahdi Dibaiee 2014-02-09 19:08:14 +03:30
parent ee48892fee
commit dda48b1b97
27 changed files with 1665 additions and 301 deletions

BIN
Mobile/css/imgs/load.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

604
Mobile/css/main.css Normal file
View File

@ -0,0 +1,604 @@
@font-face {
font-family: 'MozTT-Regular';
src: url('fonts/MozTT-Regular.ttf');
}
@font-face {
font-family: 'MozTT-Light';
src: url('fonts/MozTT-Light.ttf');
}
@font-face {
font-family: 'MozTT-Medium';
src: url('fonts/MozTT-Medium.ttf');
}
@font-face {
font-family: 'MozTT-Bold';
src: url('fonts/MozTT-Bold.ttf');
}
/* Purty Picker Copyright 2013 Jayden Seric (MIT license): https://github.com/jaydenseric/Purty-Picker */
/* Core: No touchy! */
.color-picker .spectrum {
position: relative;
/* To position pin, luminosity filter */
background: linear-gradient(#808080, transparent), linear-gradient(90deg, #ff0000, #ff2b00, #ff5500, #ff8000, #ffaa00, #ffd500, #ffff00, #d4ff00, #aaff00, #80ff00, #55ff00, #2bff00, #00ff00, #00ff2b, #00ff55, #00ff80, #00ffaa, #00ffd5, #00ffff, #00d4ff, #00aaff, #007fff, #0055ff, #002bff, #0000ff, #2a00ff, #5500ff, #7f00ff, #aa00ff, #d400ff, #ff00ff, #ff00d4, #ff00aa, #ff0080, #ff0055, #ff002b, #ff0000);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Prevent pin interaction causing content selection */
cursor: crosshair;
}
.color-picker .spectrum.active {
cursor: none;
}
.color-picker .spectrum.active .pin {
cursor: none;
}
.color-picker .spectrum > div {
/* Luminosity filter */
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.color-picker .spectrum .pin {
position: absolute;
cursor: move;
}
/* Customization: Default skin */
.color-picker {
margin: 20px;
padding: 11px;
border: 1px solid #e3e3e3;
border-radius: 4px;
background-color: #f5f5f5;
}
.color-picker .color,
.color-picker .luminosity {
-moz-box-sizing: border-box;
box-sizing: border-box;
display: block;
width: 100%;
}
.color-picker .format {
display: block;
margin: 0 auto 10px auto;
}
.color-picker .color {
-webkit-appearance: none;
border: 0;
border-radius: 2px;
padding: 10px;
text-align: center;
font-size: 11px;
letter-spacing: 1px;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
color: rgba(0, 0, 0, 0.6);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
transition: color 0.2s;
}
.color-picker .color.dark {
color: rgba(255, 255, 255, 0.7);
}
.color-picker .spectrum {
height: 150px;
/* Arbitary but required */
overflow: hidden;
/* Prevent pin overflowing container */
border-radius: 2px;
margin: 10px 0;
}
.color-picker .spectrum > div {
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
}
.color-picker .spectrum .pin {
margin-left: -4px;
margin-top: -4px;
width: 4px;
height: 4px;
border: 2px solid white;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
border-radius: 100%;
}
.color-picker .luminosity {
margin: 0;
}
/* ----------------------------------
* Seekbars
* ---------------------------------- */
div[role="slider"] {
position: relative;
height: 3.5rem;
}
div[role="slider"] > div {
display: block;
padding: 0;
overflow-y: hidden;
position: relative;
height: 100%;
}
div[role="slider"] progress {
width: 100%;
background: #000;
border: none;
height: 0.1rem;
display: block;
border-radius: 0;
margin-top: 1.9rem;
}
div[role="slider"] progress::-moz-progress-bar {
background: #01c5ed;
height: 0.6rem;
margin-top: -0.3rem;
border-radius: 0;
}
div[role="slider"] > label {
font-size: 1.5rem;
line-height: 3.8rem;
font-family: sans-serif;
color: #00aacb;
float: right;
padding: 0 0 0 1rem;
height: 3.5rem;
width: auto;
}
div[role="slider"] label:first-of-type {
float: left;
padding: 0 1rem 0 0;
}
div[role="slider"] > label.icon {
width: 3rem;
height: 3rem;
margin-top: 0.5rem;
font-size: 0;
background: no-repeat right top / 3rem auto;
}
div[role="slider"] > label.icon:first-of-type {
background-position: top left;
}
div[role="slider"] button {
width: 3.2rem;
height: 3.2rem;
background: url(seekbars/images/ui/handler.png) no-repeat center center / 3rem auto;
font: 0/0 a;
position: absolute;
top: 50%;
left: 0;
margin: -1.5rem 0 0 -1.6rem;
border-radius: 3.2rem;
border: solid 0.1rem transparent;
transition: border 0.15s ease;
padding: 0;
z-index: 10;
}
div[role="slider"] button:active {
border: solid 0.5rem #01c5ed;
}
/* ----------------------------------
* Value selector (Single & Multiple)
* ---------------------------------- */
/* Main dialog setup */
form[role="dialog"][data-type="value-selector"] {
background: url(value_selector/images/ui/pattern.png) repeat left top, url(value_selector/images/ui/gradient.png) no-repeat left top / 100% 100%;
overflow: hidden;
position: absolute;
z-index: 100;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0 0 7rem;
color: #fff;
font-family: sans-serif;
}
form[role="dialog"][data-type="value-selector"] > section {
padding: 0 1.5rem 0;
-moz-box-sizing: padding-box;
width: 100%;
height: 100%;
overflow: auto;
}
form[role="dialog"][data-type="value-selector"] h1 {
font-weight: 400;
font-size: 1.9rem;
line-height: 4.8rem;
color: #fff;
border-bottom: 0.1rem solid #616262;
background: rgba(0, 0, 0, 0.2);
margin: 0 -1.5rem;
padding: 0 3rem 1rem;
height: 4.8rem;
-moz-box-sizing: border-box;
}
/* Specific component code */
form[role="dialog"][data-type="value-selector"] [role="listbox"] {
position: relative;
padding: 0;
margin: 0 -1.5rem;
max-height: calc(95%);
overflow: auto;
border-top: solid 0.1rem #222323;
}
form[role="dialog"][data-type="value-selector"] .scrollable:before {
content: "";
display: block;
position: absolute;
pointer-events: none;
top: 4.8rem;
left: 0;
right: 0;
bottom: 6.9rem;
background: url(value_selector/images/ui/shadow.png) repeat-x left top, url(value_selector/images/ui/shadow-invert.png) repeat-x left bottom;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li {
margin: 0;
padding: 0 1.5rem;
height: auto;
list-style: none;
position: relative;
font-weight: lighter;
font-size: 2.2rem;
line-height: 3.9rem;
color: #fff;
transition: background-color 0.2s ease;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:first-child label {
border-top-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li label {
outline: none;
display: block;
color: #fff;
border-top: 0.1rem solid #666;
border-bottom: 0.1rem solid #000;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:last-child label {
border-bottom-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li label span {
display: block;
padding: 1rem 1.5rem;
line-height: 4rem;
word-wrap: break-word;
}
/* Pressed status */
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active {
background-color: #00ABCC;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label {
border-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active + li label {
border-top-color: #000;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label span {
color: #fff !important;
background-image: none;
}
/* Checked status */
form[role="dialog"][data-type="value-selector"] [role="listbox"] li[aria-selected="true"]:not([data-input]) span {
padding-right: 2.6rem;
margin-right: 1.2rem;
color: #00abcd;
background: transparent url(value_selector/images/icons/checked.png) no-repeat 100% 50%;
background-size: 2rem;
}
/* Menu & buttons setup */
form[role="dialog"][data-type="value-selector"] menu {
white-space: nowrap;
margin: 0;
padding: 1.5rem;
border-top: solid 0.1rem rgba(255, 255, 255, 0.1);
background: #2d2d2d url(value_selector/images/ui/pattern.png) repeat left top;
display: block;
overflow: hidden;
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
form[role="dialog"][data-type="value-selector"] menu button::-moz-focus-inner {
border: none;
outline: none;
}
form[role="dialog"][data-type="value-selector"] menu button {
width: calc(49.5%);
height: 3.8rem;
margin: 0 0 1rem;
padding: 0 1.5rem;
-moz-box-sizing: border-box;
display: inline-block;
vertical-align: middle;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
background: #fafafa url(value_selector/images/ui/default.png) repeat-x left bottom / auto 100%;
border: 0.1rem solid #a6a6a6;
border-radius: 0.3rem;
font-weight: 500;
font-size: 1.6rem;
line-height: 3.8rem;
color: #333;
text-align: center;
text-shadow: 0.1rem 0.1rem 0 rgba(255, 255, 255, 0.3);
text-decoration: none;
outline: none;
}
/* Press (default & affirmative) */
form[role="dialog"][data-type="value-selector"] menu button:active,
form[role="dialog"][data-type="value-selector"] menu button.affirmative:active {
border-color: #008aaa;
background: #008aaa;
color: #333;
}
/* affirmative */
form[role="dialog"][data-type="value-selector"] menu button.affirmative {
background-image: url(value_selector/images/ui/affirmative.png);
background-color: #00caf2;
border-color: #008eab;
}
form[role="dialog"][data-type="value-selector"] menu button:last-child {
margin-left: 1rem;
}
form[role="dialog"][data-type="value-selector"] menu button,
form[role="dialog"][data-type="value-selector"] menu button:first-child {
margin: 0;
}
form[role="dialog"][data-type="value-selector"] menu button.full {
width: 100%;
}
/* Right to left tweaks */
html[dir="rtl"] #value-selector li input:checked + span,
html[dir="rtl"] #value-selector li[aria-selected="true"] span {
padding-left: 2.6rem;
margin-left: 1.2rem;
}
html,
body {
margin: 0;
font-size: 10px;
overflow: hidden;
}
*::-moz-focus-inner {
border: none;
}
*:focus {
outline: none;
}
.hidden {
display: none;
visibility: none;
}
div#container {
position: absolute;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
.separator {
display: block;
height: 4.8rem;
width: 0.1rem;
}
.separator.long {
background: url('imgs/div_line_lg_black.png');
}
.separator.small {
background: url('imgs/div_line_sm_black.png');
}
.separator.left {
float: left;
}
.separator.right {
float: right;
}
.separator.menu {
position: relative;
left: -3rem;
}
.overlay {
z-index: 9999;
position: absolute;
left: 0;
top: 5.3rem;
}
button {
-moz-appearance: none;
z-index: 1;
position: relative;
border: none;
}
.close {
display: block;
width: 2rem;
height: 2rem;
padding: 0 0 0.2rem 0.2rem;
font-size: 10pt;
border: 1px solid #e3e3e3;
border-radius: 50%;
position: absolute;
text-align: center;
top: -2%;
left: 97%;
}
.picker,
.about {
font-family: 'MozTT-Light';
width: 30rem;
height: 24.6rem;
position: absolute;
left: 50%;
top: 50%;
margin-top: -12.3rem;
margin-left: -15rem;
}
.picker .color-picker,
.about .color-picker {
margin: 0;
}
.about {
background: #262626;
padding: 1rem 2rem;
height: 23rem;
margin-top: -11.5rem;
margin-left: -17rem;
border-radius: 0.2rem;
color: white;
box-shadow: 0 0 0.3rem black;
}
.about a,
.about a:link,
.about a:visited,
.about a:active {
color: white;
}
.about .close {
background: #262626;
color: white;
border: 1px solid gray;
}
.about p {
font-size: 11pt;
}
.about span {
font-size: 8pt;
}
header {
width: 100%;
height: 5.3rem;
background: url('imgs/header_bg_black.png');
}
header button {
width: 5rem;
height: 5rem;
}
header .menu {
background: url('imgs/menu.png') -12px center no-repeat;
float: left;
}
header .menu:active {
background: url('imgs/menu.png') -12px center no-repeat, url('imgs/bg_overlay_pressed_1.png') left no-repeat;
}
header .save {
background: url('imgs/download.png') center center no-repeat;
float: right;
}
header .save:active {
background: url('imgs/download.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
header .load {
background: url('imgs/load.png') center center no-repeat;
float: right;
}
header .load:active {
background: url('imgs/load.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
header #title {
color: white;
font-size: 11pt;
font-family: 'MozTT-Regular';
float: left;
margin: 1.5rem 0;
position: relative;
left: -2rem;
}
#menu {
height: 100%;
width: 15rem;
background: #262626;
position: absolute;
left: -15rem;
top: 5rem;
color: white;
font-family: 'MozTT-Light';
font-size: 8pt;
transition: left 0.2s ease-out;
border-collapse: collapse;
overflow: hidden;
}
#menu.pulled {
left: 0;
transition: left 0.2s ease-out;
}
#menu button[id^='set'],
#menu p,
#menu .bottom button {
background: none;
display: block;
width: 75%;
color: white;
text-align: left;
margin: 1rem 2.5rem;
font-family: 'MozTT-Light';
font-size: 8pt;
padding: 0 0.6rem;
cursor: pointer;
}
#menu span {
float: right;
font-size: 7pt;
}
#menu div[role='slider'] {
width: 60%;
float: right;
margin: 0 2rem 0 0;
}
#menu div[role='slider'] div {
overflow: visible;
}
#menu div[role='slider'] div button {
margin-top: -3.4rem;
left: 0%;
}
#menu hr {
clear: both;
padding: 0.7rem 0;
margin-bottom: 0.7rem;
border: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
#menu *[class^='icon'] {
display: block;
margin: 1rem 0.5rem;
}
#menu *[class^='icon']:nth-of-type(2) {
padding-top: 0.5rem;
}
#menu *[class^='icon']:before {
content: '';
background-size: 2rem;
width: 2rem;
height: 2rem;
display: block;
float: left;
margin: -0.3rem 0.5rem 0 0;
}
#menu .icon-settings:before {
background-image: url('imgs/settings.png');
}
#menu .icon-clear:before {
background-image: url('imgs/clear.png');
}
#menu .icon-undo:before {
background-image: url('imgs/undo.png');
}
#menu .icon-redo:before {
background-image: url('imgs/redo.png');
}
#menu .options {
display: block;
margin-top: 1rem;
}
#menu .bottom {
position: absolute;
bottom: 5rem;
width: 100%;
}
#menu .bottom button[class^='icon'] {
margin-left: 3.5rem;
}
#menu .bottom button {
margin-left: 5rem;
}

View File

@ -1,4 +1,7 @@
@import 'fonts';
@import 'color-picker';
@import 'seekbars';
@import 'value_selector';
html, body {
@ -148,6 +151,14 @@ header {
}
}
.load {
background: url('imgs/load.png') center center no-repeat;
float: right;
&:active {
background: url('imgs/load.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
}
#title {
color: white;
font-size: 11pt;

View File

@ -22,6 +22,7 @@ form[role="dialog"][data-type="value-selector"] > section {
-moz-box-sizing: padding-box;
width: 100%;
height: 100%;
overflow: auto;
}
form[role="dialog"][data-type="value-selector"] h1 {

View File

@ -4,13 +4,7 @@
<head>
<title>Sketchy</title>
<meta charset='UTF-8'>
<link rel='stylesheet/less' href='css/main.less'>
<link rel='stylesheet' href='css/switches.css'>
<link rel='stylesheet' href='css/value_selector.css'>
<link rel='stylesheet' href='css/seekbars.css'>
<link rel='stylesheet' href='css/color-picker.css'>
<script src='js/less-1.5.0.min.js'></script>
<script src='js/libs/mobilebrowsers.js'></script>
<link rel='stylesheet' href='css/main.css'>
</head>
<body>
@ -21,6 +15,7 @@
<p id='title'>Sketchy</p>
<button class='save'></button>
<span class='separator small right'></span>
<button class='load'></button>
</header>
<div id='container'>
@ -131,6 +126,11 @@
<form role='dialog' data-type='value-selector' id='save' class='hidden confirm'>
<section class='scrollable'>
<h1>Save</h1>
<h1>Type</h1>
<ol role='listbox'>
<li id='exp' aria-selected='true'><label><span>Export to Image</span></label></li>
<li id='pro'><label><span>Sketchy Project</span></label></li>
</ol>
<h1>Background</h1>
<ol role='listbox'>
<li aria-selected='true'><label><span>White</span></label></li>
@ -141,6 +141,8 @@
<ol role='listbox'>
<li aria-selected='true' data-input><label><span contenteditable>My Sketch</span></label></li>
</ol>
<br>
<span class='special'>Note: You must disable pop-up blocker to save your sketch.</span>
</section>
<menu>
<button class='affirmative' type='button'>Cancel</button>
@ -148,6 +150,19 @@
</menu>
</form>
<form role='dialog' data-type='value-selector' id='load' class='hidden confirm'>
<section class='scrollable'>
<h1>Load</h1>
<h1 class='hidden'>file</h1>
<ol role='listbox'>
</ol>
</section>
<menu>
<button class='affirmative' type='button'>Cancel</button>
<button class='affirmative' type='button'>Load</button>
</menu>
</form>
<!-- COLOR PICKER -->
<div class='picker overlay hidden'>
@ -181,13 +196,13 @@
<!-- PRELOADER -->
<div class='hidden'>
<img src='value_selector/images/ui/pattern.png'>
<img src='value_selector/images/ui/gradient.png'>
<img src='value_selector/images/ui/shadow.png'>
<img src='value_selector/images/ui/shadow-invert.png'>
<img src='value_selector/images/icons/checked.png'>
<img src='value_selector/images/ui/default.png'>
<img src='value_selector/images/ui/affirmative.png'>
<img src='css/value_selector/images/ui/pattern.png'>
<img src='css/value_selector/images/ui/gradient.png'>
<img src='css/value_selector/images/ui/shadow.png'>
<img src='css/value_selector/images/ui/shadow-invert.png'>
<img src='css/value_selector/images/icons/checked.png'>
<img src='css/value_selector/images/ui/default.png'>
<img src='css/value_selector/images/ui/affirmative.png'>
</div>
<script src='js/libs/zepto.min.js'></script>

View File

@ -51,17 +51,39 @@ window.save = function() {
}
}
var data = $c[0].toDataURL();
var file = dataToBlob($c[0].toDataURL());
var pics = navigator.getDeviceStorage('pictures');
var r = pics.addNamed(file, save['file name'] + '.png');
r.onsuccess = function() {
alert('Your sketch was successfuly saved to ' + this.result);
}
r.onerror = function() {
alert('Something bad happened when we tried to save your file\n Possible problems: \n Duplicate name \n Permission problems')
if( save.type == 'sketchy project' ) {
if( localStorage.getItem(save['file name']) ) {
if( confirm('A sketch with this name already exists. Do you want to overwrite ' + save['file name']) + '?' ) {
localStorage.setItem(save['file name'], JSON.stringify({data: data, points: window.points}));
}
}
else
localStorage.setItem(save['file name'], JSON.stringify({data: data, points: window.points}));
} else {
var file = dataToBlob($c[0].toDataURL());
var pics = navigator.getDeviceStorage('pictures');
var r = pics.addNamed(file, save['file name'] + '.png');
r.onsuccess = function() {
alert('Your sketch was successfuly saved to ' + this.result);
}
r.onerror = function() {
alert('Something bad happened when we tried to save your file\n Possible problems: \n Duplicate name \n Permission problems')
}
}
c.putImageData(window.points.history[window.points.history.last].data, 0, 0);
}
window.load = function() {
var file = JSON.parse(localStorage.getItem(load.file));
var img = document.createElement('img');
img.src = file.data;
console.log(file.data);
img.onload = function() {
c.clearRect(0, 0, width(), height());
c.drawImage(img, 0, 0);
window.points = file.points;
window.points.history = [{ data: c.createImageData($c.width(), $c.height()), points: []}, { data: c.getImageData(0, 0, width(), height()), points: file.points}];
}
}
$('.menu').tap(function() {
$('#menu').toggleClass('pulled');
@ -69,6 +91,36 @@ window.save = function() {
$('.save').tap(function() {
$('#save').removeClass('hidden');
})
$('.load').tap(function() {
$('#load').removeClass('hidden');
$('#load li').remove();
for( var i = 0, len = localStorage.length; i < len; i++ ) {
$('#load ol').append(
$('<li><label><span>' + localStorage.key(i) + '</span></label></li>')
);
}
if( localStorage.length < 1 ) {
$('#load ol').append(
$('<p>No Sketch found.</p>')
);
}
$confirm.find('li').off('tap').tap(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
})
$('#pro').click(function() {
$('#save ol:nth-of-type(2) li').each(function() {
if( $(this).find('span').html() !== 'Transparent' ) {
$(this).addClass('hidden');
$(this).removeAttr('aria-selected');
}
else $(this).attr('aria-selected', 'true');
})
})
$('#exp').click(function() {
$('#save ol:nth-of-type(2) li').removeClass('hidden');
})
$c.last().on('touchstart', function(e) {
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
startPoint(xy.x, xy.y);
@ -126,28 +178,31 @@ window.save = function() {
var $confirm = $('form[data-type="value-selector"].confirm');
$confirm.find('li').tap(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$confirm.find('button').last().tap(function(e) {
e.preventDefault();
var v = $(this).parents('form').attr('id');
$(this).parents('form').find('h1').each(function(i) {
if( i > 0 ) {
var key = $(this).html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
if( key !== 'file name' ) value = value.toLowerCase();
window[v][key] = value;
}
$confirm.each(function() {
$(this).find('li').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$confirm.find('button').first().tap(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
$(this).find('button').last().click(function(e) {
e.preventDefault();
var v = $(this).parents('form').attr('id');
$(this).parents('form').find('h1').each(function(i) {
if( i > 0 ) {
var key = $(this).html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
if( key !== 'file name' && key !== 'file' ) value = value.toLowerCase();
window[v][key] = value;
}
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$(this).find('button').first().click(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
})
})
// Value Selector Callers

View File

@ -1,7 +1,7 @@
{
"name": "Sketchy",
"description": "Free Sketch/Paint app",
"version": "1.1",
"version": "1.2",
"fullscreen": "true",
"type": "privileged",
"launch_path": "/index.html",

View File

@ -21,6 +21,10 @@ Firefox Marketplace: https://marketplace.firefox.com/app/sketchy/
Changelog
=========
**1.2**
* Added an option to save sketches as a project, so they are editable[1]
* Made Firefox Desktop / Firefox Android versions working ( was blocked by [1] )
**1.1**
* Added "About"
* No load-time for Mobile

View File

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Mahdi Dibaiee
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,4 +0,0 @@
Brush
=====
An image manipulation tool written in Javascript

BIN
Web/css/imgs/load.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

604
Web/css/main.css Normal file
View File

@ -0,0 +1,604 @@
@font-face {
font-family: 'MozTT-Regular';
src: url('fonts/MozTT-Regular.ttf');
}
@font-face {
font-family: 'MozTT-Light';
src: url('fonts/MozTT-Light.ttf');
}
@font-face {
font-family: 'MozTT-Medium';
src: url('fonts/MozTT-Medium.ttf');
}
@font-face {
font-family: 'MozTT-Bold';
src: url('fonts/MozTT-Bold.ttf');
}
/* Purty Picker Copyright 2013 Jayden Seric (MIT license): https://github.com/jaydenseric/Purty-Picker */
/* Core: No touchy! */
.color-picker .spectrum {
position: relative;
/* To position pin, luminosity filter */
background: linear-gradient(#808080, transparent), linear-gradient(90deg, #ff0000, #ff2b00, #ff5500, #ff8000, #ffaa00, #ffd500, #ffff00, #d4ff00, #aaff00, #80ff00, #55ff00, #2bff00, #00ff00, #00ff2b, #00ff55, #00ff80, #00ffaa, #00ffd5, #00ffff, #00d4ff, #00aaff, #007fff, #0055ff, #002bff, #0000ff, #2a00ff, #5500ff, #7f00ff, #aa00ff, #d400ff, #ff00ff, #ff00d4, #ff00aa, #ff0080, #ff0055, #ff002b, #ff0000);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Prevent pin interaction causing content selection */
cursor: crosshair;
}
.color-picker .spectrum.active {
cursor: none;
}
.color-picker .spectrum.active .pin {
cursor: none;
}
.color-picker .spectrum > div {
/* Luminosity filter */
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.color-picker .spectrum .pin {
position: absolute;
cursor: move;
}
/* Customization: Default skin */
.color-picker {
margin: 20px;
padding: 11px;
border: 1px solid #e3e3e3;
border-radius: 4px;
background-color: #f5f5f5;
}
.color-picker .color,
.color-picker .luminosity {
-moz-box-sizing: border-box;
box-sizing: border-box;
display: block;
width: 100%;
}
.color-picker .format {
display: block;
margin: 0 auto 10px auto;
}
.color-picker .color {
-webkit-appearance: none;
border: 0;
border-radius: 2px;
padding: 10px;
text-align: center;
font-size: 11px;
letter-spacing: 1px;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
color: rgba(0, 0, 0, 0.6);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
transition: color 0.2s;
}
.color-picker .color.dark {
color: rgba(255, 255, 255, 0.7);
}
.color-picker .spectrum {
height: 150px;
/* Arbitary but required */
overflow: hidden;
/* Prevent pin overflowing container */
border-radius: 2px;
margin: 10px 0;
}
.color-picker .spectrum > div {
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
}
.color-picker .spectrum .pin {
margin-left: -4px;
margin-top: -4px;
width: 4px;
height: 4px;
border: 2px solid white;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
border-radius: 100%;
}
.color-picker .luminosity {
margin: 0;
}
/* ----------------------------------
* Seekbars
* ---------------------------------- */
div[role="slider"] {
position: relative;
height: 3.5rem;
}
div[role="slider"] > div {
display: block;
padding: 0;
overflow-y: hidden;
position: relative;
height: 100%;
}
div[role="slider"] progress {
width: 100%;
background: #000;
border: none;
height: 0.1rem;
display: block;
border-radius: 0;
margin-top: 1.9rem;
}
div[role="slider"] progress::-moz-progress-bar {
background: #01c5ed;
height: 0.6rem;
margin-top: -0.3rem;
border-radius: 0;
}
div[role="slider"] > label {
font-size: 1.5rem;
line-height: 3.8rem;
font-family: sans-serif;
color: #00aacb;
float: right;
padding: 0 0 0 1rem;
height: 3.5rem;
width: auto;
}
div[role="slider"] label:first-of-type {
float: left;
padding: 0 1rem 0 0;
}
div[role="slider"] > label.icon {
width: 3rem;
height: 3rem;
margin-top: 0.5rem;
font-size: 0;
background: no-repeat right top / 3rem auto;
}
div[role="slider"] > label.icon:first-of-type {
background-position: top left;
}
div[role="slider"] button {
width: 3.2rem;
height: 3.2rem;
background: url(seekbars/images/ui/handler.png) no-repeat center center / 3rem auto;
font: 0/0 a;
position: absolute;
top: 50%;
left: 0;
margin: -1.5rem 0 0 -1.6rem;
border-radius: 3.2rem;
border: solid 0.1rem transparent;
transition: border 0.15s ease;
padding: 0;
z-index: 10;
}
div[role="slider"] button:active {
border: solid 0.5rem #01c5ed;
}
/* ----------------------------------
* Value selector (Single & Multiple)
* ---------------------------------- */
/* Main dialog setup */
form[role="dialog"][data-type="value-selector"] {
background: url(value_selector/images/ui/pattern.png) repeat left top, url(value_selector/images/ui/gradient.png) no-repeat left top / 100% 100%;
overflow: hidden;
position: absolute;
z-index: 100;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0 0 7rem;
color: #fff;
font-family: sans-serif;
}
form[role="dialog"][data-type="value-selector"] > section {
padding: 0 1.5rem 0;
-moz-box-sizing: padding-box;
width: 100%;
height: 100%;
overflow: auto;
}
form[role="dialog"][data-type="value-selector"] h1 {
font-weight: 400;
font-size: 1.9rem;
line-height: 4.8rem;
color: #fff;
border-bottom: 0.1rem solid #616262;
background: rgba(0, 0, 0, 0.2);
margin: 0 -1.5rem;
padding: 0 3rem 1rem;
height: 4.8rem;
-moz-box-sizing: border-box;
}
/* Specific component code */
form[role="dialog"][data-type="value-selector"] [role="listbox"] {
position: relative;
padding: 0;
margin: 0 -1.5rem;
max-height: calc(95%);
overflow: auto;
border-top: solid 0.1rem #222323;
}
form[role="dialog"][data-type="value-selector"] .scrollable:before {
content: "";
display: block;
position: absolute;
pointer-events: none;
top: 4.8rem;
left: 0;
right: 0;
bottom: 6.9rem;
background: url(value_selector/images/ui/shadow.png) repeat-x left top, url(value_selector/images/ui/shadow-invert.png) repeat-x left bottom;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li {
margin: 0;
padding: 0 1.5rem;
height: auto;
list-style: none;
position: relative;
font-weight: lighter;
font-size: 2.2rem;
line-height: 3.9rem;
color: #fff;
transition: background-color 0.2s ease;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:first-child label {
border-top-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li label {
outline: none;
display: block;
color: #fff;
border-top: 0.1rem solid #666;
border-bottom: 0.1rem solid #000;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:last-child label {
border-bottom-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li label span {
display: block;
padding: 1rem 1.5rem;
line-height: 4rem;
word-wrap: break-word;
}
/* Pressed status */
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active {
background-color: #00ABCC;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label {
border-color: transparent;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active + li label {
border-top-color: #000;
}
form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label span {
color: #fff !important;
background-image: none;
}
/* Checked status */
form[role="dialog"][data-type="value-selector"] [role="listbox"] li[aria-selected="true"]:not([data-input]) span {
padding-right: 2.6rem;
margin-right: 1.2rem;
color: #00abcd;
background: transparent url(value_selector/images/icons/checked.png) no-repeat 100% 50%;
background-size: 2rem;
}
/* Menu & buttons setup */
form[role="dialog"][data-type="value-selector"] menu {
white-space: nowrap;
margin: 0;
padding: 1.5rem;
border-top: solid 0.1rem rgba(255, 255, 255, 0.1);
background: #2d2d2d url(value_selector/images/ui/pattern.png) repeat left top;
display: block;
overflow: hidden;
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
form[role="dialog"][data-type="value-selector"] menu button::-moz-focus-inner {
border: none;
outline: none;
}
form[role="dialog"][data-type="value-selector"] menu button {
width: calc(49.5%);
height: 3.8rem;
margin: 0 0 1rem;
padding: 0 1.5rem;
-moz-box-sizing: border-box;
display: inline-block;
vertical-align: middle;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
background: #fafafa url(value_selector/images/ui/default.png) repeat-x left bottom / auto 100%;
border: 0.1rem solid #a6a6a6;
border-radius: 0.3rem;
font-weight: 500;
font-size: 1.6rem;
line-height: 3.8rem;
color: #333;
text-align: center;
text-shadow: 0.1rem 0.1rem 0 rgba(255, 255, 255, 0.3);
text-decoration: none;
outline: none;
}
/* Press (default & affirmative) */
form[role="dialog"][data-type="value-selector"] menu button:active,
form[role="dialog"][data-type="value-selector"] menu button.affirmative:active {
border-color: #008aaa;
background: #008aaa;
color: #333;
}
/* affirmative */
form[role="dialog"][data-type="value-selector"] menu button.affirmative {
background-image: url(value_selector/images/ui/affirmative.png);
background-color: #00caf2;
border-color: #008eab;
}
form[role="dialog"][data-type="value-selector"] menu button:last-child {
margin-left: 1rem;
}
form[role="dialog"][data-type="value-selector"] menu button,
form[role="dialog"][data-type="value-selector"] menu button:first-child {
margin: 0;
}
form[role="dialog"][data-type="value-selector"] menu button.full {
width: 100%;
}
/* Right to left tweaks */
html[dir="rtl"] #value-selector li input:checked + span,
html[dir="rtl"] #value-selector li[aria-selected="true"] span {
padding-left: 2.6rem;
margin-left: 1.2rem;
}
html,
body {
margin: 0;
font-size: 10px;
overflow: hidden;
}
*::-moz-focus-inner {
border: none;
}
*:focus {
outline: none;
}
.hidden {
display: none;
visibility: none;
}
div#container {
position: absolute;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
.separator {
display: block;
height: 4.8rem;
width: 0.1rem;
}
.separator.long {
background: url('imgs/div_line_lg_black.png');
}
.separator.small {
background: url('imgs/div_line_sm_black.png');
}
.separator.left {
float: left;
}
.separator.right {
float: right;
}
.separator.menu {
position: relative;
left: -3rem;
}
.overlay {
z-index: 9999;
position: absolute;
left: 0;
top: 5.3rem;
}
button {
-moz-appearance: none;
z-index: 1;
position: relative;
border: none;
}
.close {
display: block;
width: 2rem;
height: 2rem;
padding: 0 0 0.2rem 0.2rem;
font-size: 10pt;
border: 1px solid #e3e3e3;
border-radius: 50%;
position: absolute;
text-align: center;
top: -2%;
left: 97%;
}
.picker,
.about {
font-family: 'MozTT-Light';
width: 30rem;
height: 24.6rem;
position: absolute;
left: 50%;
top: 50%;
margin-top: -12.3rem;
margin-left: -15rem;
}
.picker .color-picker,
.about .color-picker {
margin: 0;
}
.about {
background: #262626;
padding: 1rem 2rem;
height: 23rem;
margin-top: -11.5rem;
margin-left: -17rem;
border-radius: 0.2rem;
color: white;
box-shadow: 0 0 0.3rem black;
}
.about a,
.about a:link,
.about a:visited,
.about a:active {
color: white;
}
.about .close {
background: #262626;
color: white;
border: 1px solid gray;
}
.about p {
font-size: 11pt;
}
.about span {
font-size: 8pt;
}
header {
width: 100%;
height: 5.3rem;
background: url('imgs/header_bg_black.png');
}
header button {
width: 5rem;
height: 5rem;
}
header .menu {
background: url('imgs/menu.png') -12px center no-repeat;
float: left;
}
header .menu:active {
background: url('imgs/menu.png') -12px center no-repeat, url('imgs/bg_overlay_pressed_1.png') left no-repeat;
}
header .save {
background: url('imgs/download.png') center center no-repeat;
float: right;
}
header .save:active {
background: url('imgs/download.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
header .load {
background: url('imgs/load.png') center center no-repeat;
float: right;
}
header .load:active {
background: url('imgs/load.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
header #title {
color: white;
font-size: 11pt;
font-family: 'MozTT-Regular';
float: left;
margin: 1.5rem 0;
position: relative;
left: -2rem;
}
#menu {
height: 100%;
width: 15rem;
background: #262626;
position: absolute;
left: -15rem;
top: 5rem;
color: white;
font-family: 'MozTT-Light';
font-size: 8pt;
transition: left 0.2s ease-out;
border-collapse: collapse;
overflow: hidden;
}
#menu.pulled {
left: 0;
transition: left 0.2s ease-out;
}
#menu button[id^='set'],
#menu p,
#menu .bottom button {
background: none;
display: block;
width: 75%;
color: white;
text-align: left;
margin: 1rem 2.5rem;
font-family: 'MozTT-Light';
font-size: 8pt;
padding: 0 0.6rem;
cursor: pointer;
}
#menu span {
float: right;
font-size: 7pt;
}
#menu div[role='slider'] {
width: 60%;
float: right;
margin: 0 2rem 0 0;
}
#menu div[role='slider'] div {
overflow: visible;
}
#menu div[role='slider'] div button {
margin-top: -3.4rem;
left: 0%;
}
#menu hr {
clear: both;
padding: 0.7rem 0;
margin-bottom: 0.7rem;
border: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
#menu *[class^='icon'] {
display: block;
margin: 1rem 0.5rem;
}
#menu *[class^='icon']:nth-of-type(2) {
padding-top: 0.5rem;
}
#menu *[class^='icon']:before {
content: '';
background-size: 2rem;
width: 2rem;
height: 2rem;
display: block;
float: left;
margin: -0.3rem 0.5rem 0 0;
}
#menu .icon-settings:before {
background-image: url('imgs/settings.png');
}
#menu .icon-clear:before {
background-image: url('imgs/clear.png');
}
#menu .icon-undo:before {
background-image: url('imgs/undo.png');
}
#menu .icon-redo:before {
background-image: url('imgs/redo.png');
}
#menu .options {
display: block;
margin-top: 1rem;
}
#menu .bottom {
position: absolute;
bottom: 5rem;
width: 100%;
}
#menu .bottom button[class^='icon'] {
margin-left: 3.5rem;
}
#menu .bottom button {
margin-left: 5rem;
}

View File

@ -1,4 +1,7 @@
@import 'fonts';
@import 'color-picker';
@import 'seekbars';
@import 'value_selector';
html, body {
@ -148,6 +151,14 @@ header {
}
}
.load {
background: url('imgs/load.png') center center no-repeat;
float: right;
&:active {
background: url('imgs/load.png') center center no-repeat, url('imgs/bg_overlay_pressed_2.png') center center;
}
}
#title {
color: white;
font-size: 11pt;

View File

@ -22,6 +22,7 @@ form[role="dialog"][data-type="value-selector"] > section {
-moz-box-sizing: padding-box;
width: 100%;
height: 100%;
overflow: auto;
}
form[role="dialog"][data-type="value-selector"] h1 {

View File

@ -5,12 +5,7 @@
<title>Sketchy</title>
<meta charset='UTF-8'>
<meta name="viewport" content="width=device-width user-scalable=no initial-scale=1">
<link rel='stylesheet/less' href='css/main.less'>
<link rel='stylesheet' href='css/switches.css'>
<link rel='stylesheet' href='css/value_selector.css'>
<link rel='stylesheet' href='css/seekbars.css'>
<link rel='stylesheet' href='css/color-picker.css'>
<script src='js/less-1.5.0.min.js'></script>
<link rel='stylesheet' href='css/main.css'>
<script src='js/libs/mobilebrowsers.js'></script>
</head>
@ -22,6 +17,7 @@
<p id='title'>Sketchy</p>
<button class='save'></button>
<span class='separator small right'></span>
<button class='load'></button>
</header>
<div id='container'>
@ -132,14 +128,23 @@
<form role='dialog' data-type='value-selector' id='save' class='hidden confirm'>
<section class='scrollable'>
<h1>Save</h1>
<h1>Type</h1>
<ol role='listbox'>
<li id='exp' aria-selected='true'><label><span>Export to Image</span></label></li>
<li id='pro'><label><span>Sketchy Project</span></label></li>
</ol>
<h1>Background</h1>
<ol role='listbox'>
<li aria-selected='true'><label><span>White</span></label></li>
<li><label><span>Current Color</span></label></li>
<li><label><span>Transparent</span></label></li>
</ol>
<h1>File Name</h1>
<ol role='listbox'>
<li aria-selected='true' data-input><label><span contenteditable>My Sketch</span></label></li>
</ol>
<br>
<span>Note: You must disable pop-up blocker to save your sketch.</span>
<span class='special'>Note: You must disable pop-up blocker to save your sketch.</span>
</section>
<menu>
<button class='affirmative' type='button'>Cancel</button>
@ -147,6 +152,19 @@
</menu>
</form>
<form role='dialog' data-type='value-selector' id='load' class='hidden confirm'>
<section class='scrollable'>
<h1>Load</h1>
<h1 class='hidden'>file</h1>
<ol role='listbox'>
</ol>
</section>
<menu>
<button class='affirmative' type='button'>Cancel</button>
<button class='affirmative' type='button'>Load</button>
</menu>
</form>
<!-- COLOR PICKER -->
<div class='picker overlay hidden'>
@ -180,13 +198,13 @@
<!-- PRELOADER -->
<div class='hidden'>
<img src='value_selector/images/ui/pattern.png'>
<img src='value_selector/images/ui/gradient.png'>
<img src='value_selector/images/ui/shadow.png'>
<img src='value_selector/images/ui/shadow-invert.png'>
<img src='value_selector/images/icons/checked.png'>
<img src='value_selector/images/ui/default.png'>
<img src='value_selector/images/ui/affirmative.png'>
<img src='css/value_selector/images/ui/pattern.png'>
<img src='css/value_selector/images/ui/gradient.png'>
<img src='css/value_selector/images/ui/shadow.png'>
<img src='css/value_selector/images/ui/shadow-invert.png'>
<img src='css/value_selector/images/icons/checked.png'>
<img src='css/value_selector/images/ui/default.png'>
<img src='css/value_selector/images/ui/affirmative.png'>
</div>
<script src='js/libs/yepnope.min.js'></script>

View File

@ -2,41 +2,42 @@
$(window).resize(sizeAndPos);
// Check for update
function save() {
var cData = c.getImageData(0, 0, width(), height());
switch(save.background) {
case 'white': {
c.fillStyle = 'white';
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
case 'current color': {
c.fillStyle = settings.color;
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
}
var data = $c[0].toDataURL();
window.open(data, '_blank').focus();
c.putImageData(cData, 0, 0);
}
$('.menu').click(function() {
$('#menu').toggleClass('pulled');
})
$('.save').click(function() {
$('#save').removeClass('hidden');
})
$('.load').click(function() {
$('#load').removeClass('hidden');
$('#load li').remove();
for( var i = 0, len = localStorage.length; i < len; i++ ) {
$('#load ol').append(
$('<li><label><span>' + localStorage.key(i) + '</span></label></li>')
);
}
if( localStorage.length < 1 ) {
$('#load ol').append(
$('<p>No sketch found.</p>')
);
}
$confirm.find('li').off('click').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
})
$('#pro').click(function() {
$('#save ol:nth-of-type(2) li').each(function() {
if( $(this).find('span').html() !== 'Transparent' ) {
$(this).addClass('hidden');
$(this).removeAttr('aria-selected');
}
else $(this).attr('aria-selected', 'true');
})
})
$('#exp').click(function() {
$('#save ol:nth-of-type(2) li').removeClass('hidden');
})
$c.last().on('mousedown', function(e) {
e.preventDefault();
var xy = relative(e.pageX, e.pageY);
@ -68,7 +69,7 @@ function save() {
// Single
var $single = $('form[data-type="value-selector"].single');
var $single = $('form.single');
$single.find('li').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
@ -90,28 +91,33 @@ function save() {
// Confirm
var $confirm = $('form[data-type="value-selector"].confirm');
var $confirm = $('form.confirm');
$confirm.find('li').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$confirm.find('button').last().click(function(e) {
e.preventDefault();
var v = $(this).parents('form').attr('id');
$(this).parents('form').find('h1').each(function(i) {
if( i > 0 ) {
var key = $(this).html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html().toLowerCase();
window[v][key] = value;
}
$confirm.each(function() {
$(this).find('li').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$confirm.find('button').first().click(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
$(this).find('button').last().click(function(e) {
e.preventDefault();
var v = $(this).parents('form').attr('id');
$(this).parents('form').find('h1').each(function(i) {
if( i > 0 ) {
var key = $(this).html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
if( key !== 'file name' && key !== 'file' ) value = value.toLowerCase();
window[v][key] = value;
}
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$(this).find('button').first().click(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
})
})
// Value Selector Callers

View File

@ -35,4 +35,65 @@ $(document).ready(function() {
nope: ['js/desktop.js', 'js/libs/color-picker.js']
})
function save() {
switch(save.background) {
case 'white': {
c.fillStyle = 'white';
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
case 'current color': {
c.fillStyle = settings.color;
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
}
var data = $c[0].toDataURL();
if( save.type == 'sketchy project' ) {
if( localStorage.getItem(save['file name']) ) {
if( confirm('A sketch with this name already exists. Do you want to overwrite ' + save['file name']) + '?' ) {
localStorage.setItem(save['file name'], JSON.stringify({data: data, points: window.points}));
}
}
else
localStorage.setItem(save['file name'], JSON.stringify({data: data, points: window.points}));
} else {
window.open(data, '_blank').focus();
}
c.putImageData(window.points.history[window.points.history.last].data, 0, 0);
}
function load() {
var file = JSON.parse(localStorage.getItem(load.file));
var img = document.createElement('img');
img.src = file.data;
img.onload = function() {
c.clearRect(0, 0, width(), height());
c.drawImage(img, 0, 0);
window.points = file.points;
window.points.history = [{ data: c.createImageData($c.width(), $c.height()), points: []}, { data: c.getImageData(0, 0, width(), height()), points: file.points}];
}
}
window.load = load;
window.save = save;
// Check for Update
var request = navigator.mozApps.getSelf();
request.onsuccess = function() {
var manifest = this.manifest;
}
})

0
Web/js/mobile.css Normal file
View File

View File

@ -1,207 +1,196 @@
"use strict";
$(document).ready(function() {
// Open External Links in browser
$('*').click(function(e) {
e.preventDefault();
$('.menu').tap(function() {
$('#menu').toggleClass('pulled');
})
$('a[href^="http"]').on('tap', function(e) {
e.preventDefault();
var href = $(this).attr('href');
var view = new MozActivity({
name: 'view',
data: {
type: 'url',
url: href
}
})
$('.save').tap(function() {
$('#save').removeClass('hidden');
})
function save() {
var cData = c.getImageData(0, 0, width(), height());
switch(save.background) {
case 'white': {
c.fillStyle = 'white';
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
case 'current color': {
c.fillStyle = settings.color;
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = settings.color;
c.globalCompositeOperation = settings.composite;
break;
}
$('.load').tap(function() {
$('#load').removeClass('hidden');
$('#load li').remove();
for( var i = 0, len = localStorage.length; i < len; i++ ) {
$('#load ol').append(
$('<li><label><span>' + localStorage.key(i) + '</span></label></li>')
);
}
var data = $c[0].toDataURL();
window.open(data, '_blank').focus();
c.putImageData(cData, 0, 0);
}
$('.menu').tap(function() {
$('#menu').toggleClass('pulled');
if( localStorage.length < 1 ) {
$('#load ol').append(
$('<p>No sketch found.</p>')
);
}
$confirm.find('li').off('tap').tap(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$('.save').tap(function() {
$('#save').removeClass('hidden');
})
$('#pro').click(function() {
$('#save ol:nth-of-type(2) li').each(function() {
if( $(this).find('span').html() !== 'Transparent' ) {
$(this).addClass('hidden');
$(this).removeAttr('aria-selected');
}
else $(this).attr('aria-selected', 'true');
})
$c.last().on('touchstart', function(e) {
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
startPoint(xy.x, xy.y);
window.active = true;
}).on('touchmove', function(e) {
if (!window.active || settings.type == 'line') return;
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
drawPoint(xy.x, xy.y);
}).on('touchend', function(e) {
})
$('#exp').click(function() {
$('#save ol:nth-of-type(2) li').removeClass('hidden');
})
$c.last().on('touchstart', function(e) {
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
startPoint(xy.x, xy.y);
window.active = true;
}).on('touchmove', function(e) {
if (!window.active || settings.type == 'line') return;
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
drawPoint(xy.x, xy.y);
}).on('touchend', function(e) {
window.active = false;
if( settings.type == 'eraser' ) return;
if(window.points.history.last < window.points.history.length-1) {
window.points.history.splice(window.points.history.last+1);
}
window.points.history.push({
data: c.getImageData(0, 0, width(), height()),
points: window.points.slice(0)
})
window.points.history.last = window.points.history.length-1;
}).on('longTap', function(e) {
if( points[points.length-1].type == 'line' ) {
window.active = false;
if( settings.type == 'eraser' ) return;
points[points.length-1].type = '';
points[points.length-1].start = undefined;
}
})
if(window.points.history.last < window.points.history.length-1) {
window.points.history.splice(window.points.history.last+1);
}
// Value Selector
window.points.history.push({
data: c.getImageData(0, 0, width(), height()),
points: window.points.slice(0)
})
window.points.history.last = window.points.history.length-1;
}).on('longTap', function(e) {
if( points[points.length-1].type == 'line' ) {
window.active = false;
points[points.length-1].type = '';
points[points.length-1].start = undefined;
}
})
var $single = $('form[data-type="value-selector"].single');
$single.find('li').tap(function(e) {
e.preventDefault();
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
var key = $(this).parents('form').attr('id'),
value = $(this).find('label span').html().toLowerCase();
window.settings[key] = value;
$('button[id="set' + key + '"] span').html(value[0].toUpperCase() + value.substr(1));
$('#menu div.options > div').addClass('hidden');
$('#menu div.options > .general, #menu div.options > .'+value).removeClass('hidden');
$(this).parents('form').addClass('hidden');
})
$single.submit(function(e) {
e.preventDefault();
$(this).addClass('hidden');
})
// Confirm
var $confirm = $('form[data-type="value-selector"].confirm');
$confirm.each(function() {
// Value Selector
var $single = $('form[data-type="value-selector"].single');
$single.find('li').tap(function(e) {
e.preventDefault();
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
var key = $(this).parents('form').attr('id'),
value = $(this).find('label span').html().toLowerCase();
window.settings[key] = value;
$('button[id="set' + key + '"] span').html(value[0].toUpperCase() + value.substr(1));
$('#menu div.options > div').addClass('hidden');
$('#menu div.options > .general, #menu div.options > .'+value).removeClass('hidden');
$(this).parents('form').addClass('hidden');
})
$single.submit(function(e) {
e.preventDefault();
$(this).addClass('hidden');
})
// Confirm
var $confirm = $('form[data-type="value-selector"].confirm');
$confirm.find('li').tap(function(e) {
$(this).find('li').click(function(e) {
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
$(this).attr('aria-selected', 'true');
})
$confirm.find('button').last().tap(function(e) {
$(this).find('button').last().click(function(e) {
e.preventDefault();
var v = $(this).parents('form').attr('id');
$(this).parents('form').find('h1').each(function(i) {
if( i > 0 ) {
var key = $(this).html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html().toLowerCase();
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
if( key !== 'file name' && key !== 'file' ) value = value.toLowerCase();
window[v][key] = value;
}
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$confirm.find('button').first().tap(function(e) {
$(this).find('button').first().click(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
})
// Value Selector Callers
var $btn = $('button[id^="set"]');
$btn.each(function() {
var target = /set(.*)/.exec($(this).attr('id'))[1];
if( target == 'color' ) {
return $(this).tap(function() {
$('.picker').removeClass('hidden');
})
}
$(this).tap(function(e) {
e.preventDefault();
$('form[id="' + target + '"]').removeClass('hidden');
})
// Value Selector Callers
var $btn = $('button[id^="set"]');
$btn.each(function() {
var target = /set(.*)/.exec($(this).attr('id'))[1];
if( target == 'color' ) {
return $(this).tap(function() {
$('.picker').removeClass('hidden');
})
}
$(this).tap(function(e) {
e.preventDefault();
$('form[id="' + target + '"]').removeClass('hidden');
})
})
// Seekbar
// Seekbar
var sliderLeft;
$('div[role="slider"] button').on('touchstart', function() {
$(this).attr('data-moving','true');
if( !sliderLeft ) sliderLeft = $('div[role="slider"] button').offset().left;
}).on('touchmove', function(e) {
if( $(this).attr('data-moving') ) {
var x = parseInt(e.changedTouches[0].pageX - sliderLeft - 15);
var $c = $('.'+$(this).parents('div[role="slider"]').attr('class'));
var progress = $c.find('progress');
var max = +progress.attr('max');
var min = +progress.attr('min');
if( x <= max && x >= min ) {
$c.find('button').css('left', x+'%');
progress.attr('value', x);
var key = $c.attr('class');
settings[key] = x;
$('#'+ key +' span').html(x);
}
var sliderLeft;
$('div[role="slider"] button').on('touchstart', function() {
$(this).attr('data-moving','true');
if( !sliderLeft ) sliderLeft = $('div[role="slider"] button').offset().left;
}).on('touchmove', function(e) {
if( $(this).attr('data-moving') ) {
var x = parseInt(e.changedTouches[0].pageX - sliderLeft - 15);
var $c = $('.'+$(this).parents('div[role="slider"]').attr('class'));
var progress = $c.find('progress');
var max = +progress.attr('max');
var min = +progress.attr('min');
if( x <= max && x >= min ) {
$c.find('button').css('left', x+'%');
progress.attr('value', x);
var key = $c.attr('class');
settings[key] = x;
$('#'+ key +' span').html(x);
}
}).on('touchend', function() {
$(this).removeAttr('data-moving');
}
}).on('touchend', function() {
$(this).removeAttr('data-moving');
})
// Color Picker
$('.close').tap(function() {
$(this).parent().addClass('hidden');
})
// Bottom
$('#clear').tap(function() {
c.clearRect(0, 0, width(), height());
var h = window.points.history;
window.points = [];
window.points.history = h;
if(window.points.history.last < window.points.history.length-1) {
window.points.history.splice(window.points.history.last+1);
}
window.points.history.push({
data: c.getImageData(0, 0, width(), height()),
points: []
})
window.points.history.last = window.points.history.length-1;
})
// Color Picker
$('.close').tap(function() {
$(this).parent().addClass('hidden');
})
$('#undo').tap(undo);
$('#redo').tap(redo);
// Bottom
$('#about').tap(function() {
$('.about').removeClass('hidden');
})
$('#clear').tap(function() {
c.clearRect(0, 0, width(), height());
var h = window.points.history;
window.points = [];
window.points.history = h;
if(window.points.history.last < window.points.history.length-1) {
window.points.history.splice(window.points.history.last+1);
}
window.points.history.push({
data: c.getImageData(0, 0, width(), height()),
points: []
})
window.points.history.last = window.points.history.length-1;
})
$('#undo').tap(undo);
$('#redo').tap(redo);
$('#about').tap(function() {
$('.about').removeClass('hidden');
})
});

View File

@ -1,7 +1,7 @@
{
"name": "Sketchy Web",
"description": "Free Sketch/Paint app",
"version": "1",
"version": "1.2",
"default_locale": "en",
"launch_path": "/Sketchy/Web/index.html",
"icons": {

View File

@ -4,13 +4,21 @@
<title>Sketchy Changelog</title>
</head>
<body>
<ul><b>1.1</b>
<ul>
<b>1.2</b>
<li>Added an option to save sketches as a project, so they are editable[1]</li>
<li>Made Firefox Desktop / Firefox Android versions working ( was blocked by [1] )</li>
<b>1.1</b>
<li>Added "About"</li>
<li>No Load-time for mobile</li>
<li>Added preloader for images</li>
<li>Fixed low lineWidth for sketches rendering invisible in Chrome</li>
<li>Fixed background settings not applying ( save )</li>
<li>Fixed Email link not working on Mobile</li>
</ul>
</body>
</html>