separated Web from Mobile

This commit is contained in:
Mahdi Dibaiee
2014-02-07 15:50:19 +03:30
parent 8af0ac91b3
commit ab58829df2
162 changed files with 2608 additions and 31 deletions

196
Mobile/js/functions.js Normal file
View File

@ -0,0 +1,196 @@
"use strict";
/*** ESSENTIALS ***/
function sizeAndPos() {
var data = window.points.history[window.points.history.last].data || c.getImageData(0,0, $c.width(), $c.height());
var w = $(window).width(),
h = $(window).height() - 53;
$c.attr('width', w * window.devicePixelRatio);
$c.attr('height',h * window.devicePixelRatio);
$c.css({
'width' : w,
'height' : h
});
c.clearRect(0,0, width(), height());
c.putImageData(data, 0, 0);
}
function relative(x,y) {
return {
x : x*window.devicePixelRatio,
y : (y - 53) * window.devicePixelRatio
}
}
function threshold(x1, y1, x2, y2, threshold) {
var tr = threshold || 5;
if( x1 <= x2 + tr && x1 >= x2 - tr && y1 <= y2 + tr && y1 >= y2 - tr ) return true;
return false;
}
function draw(x1, y1, x2, y2, opts, overlay) {
opts = opts || {};
var c = window.c;
if( overlay ) var c = window.o;
c.beginPath();
if( settings.type == 'eraser' ) c.globalCompositeOperation = 'destination-out';
else c.globalCompositeOperation = opts.composite || settings.composite;
c.lineCap = opts.lineCap || settings.lineCap;
c.lineJoin = opts.lineJoin || settings.lineJoin;
c.strokeStyle = opts.color || settings.color;
c.fillStyle = opts.color || settings.color;
c.lineWidth = ( opts.lineWidth || settings.lineWidth ) / 10;
c.moveTo(x1, y1);
c.lineTo(x2, y2);
if( !opts.noStroke ) c.stroke();
if( opts.fill ) c.fill();
}
function undo() {
var history = window.points.history;
if( history.last > 1 ) {
var step = history[history.last-1];
c.putImageData(step.data, 0, 0);
window.points = step.points.slice(0);
window.points.history = history;
window.points.history.last = history.last-1;
} else {
c.clearRect(0,0, width(), height());
window.points = [];
window.points.history = history;
window.points.history.last = 0;
}
}
function redo() {
var history = window.points.history;
if( history.last < history.length-1 ) {
var step = history[history.last+1];
c.putImageData(step.data, 0, 0);
window.points = step.points.slice(0);
window.points.history = history;
window.points.history.last = history.last+1;
}
}
function width() {
return +$c.attr('width');
}
function height() {
return +$c.attr('height');
}
function dataToBlob(data) {
var binary = atob(data.split(',')[1]), array = [];
var type = data.split(',')[0].split(':')[1].split(';')[0];
for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
return new Blob([new Uint8Array(array)], {type: type});
}
/*** END ***/
function startPoint(x, y) {
// If no previous point exists, make the first one.
if( !points.length ) points.push({x: x, y: y, type: '', start: {x: x, y: y}});
var old = points[points.length-1],
start = old.start,
current = {
x : x,
y : y,
start : old.start || {x: x, y: y},
type : settings.type
}
if( old.type !== 'line' && current.type == 'line' ) {
window.o.beginPath();
window.o.fillStyle = 'red';
window.o.arc(x,y, 3, 0, 2*Math.PI);
window.o.fill();
}
if( old.type == 'line' && current.type == 'line' ) {
if( points[points.indexOf(old)-1].type !== 'line' ) {
o.clearRect(old.x-3, old.y-3, 6, 6, true);
draw(old.x, old.y, x, y);
} else
draw(old.x, old.y, x, y);
}
var thresholds = window.mobile ? [10, 5] : [5, 2];
if( points.length > 1 && ((start && threshold(start.x, start.y, x, y, thresholds[0])) || threshold(old.x, old.y, x, y, thresholds[1])) ) {
window.active = false;
points[points.length-1].type = '';
points[points.length-1].start = undefined;
return;
}
points.push(current);
}
function drawPoint(x,y) {
var capture = points[points.length-1];
switch(capture.type) {
case 'eraser': {
capture.type = 'pen';
}
case 'pen': {
draw(capture.x, capture.y, x, y);
var current = {
x : x,
y : y,
start : capture.start,
type : capture.type
}
points.push(current);
break;
}
case 'sketch': {
draw(capture.x, capture.y, x, y);
var current = {
x : x,
y : y,
start : capture.start,
type : capture.type
}
points.push(current);
for( var i = 0, len = points.length-1; i < len; i++ ) {
if(threshold(points[i].x, points[i].y, current.x, current.y, settings.connectTelorance)) {
var x = points[i].x - current.x,
y = points[i].y - current.y;
draw(points[i].x - x*0.2, points[i].y - y*0.2, current.x + x*0.2, current.y + y*0.2, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/20})
}
}
break;
}
case 'fur': {
draw(capture.x, capture.y, x, y);
var current = {
x : x,
y : y,
start : capture.start,
type : capture.type
}
points.push(current);
for( var i = 0, len = points.length-1; i < len; i++ ) {
if(threshold(points[i].x, points[i].y, current.x, current.y, settings.connectTelorance)) {
var x = points[i].x - current.x,
y = points[i].y - current.y;
var l = settings.furLength / 100 || 0.2;
draw(points[i].x + x*l, points[i].y + y*l, current.x - x*l, current.y - y*l, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/2})
}
}
break;
}
}
}

13
Mobile/js/less-1.5.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,290 @@
/*
Purty Picker Copyright 2013 Jayden Seric (MIT license).
A super lightweight visual HSL, RGB and hex color picker with a responsive, touch-friendly and customizable UI.
Requires jQuery or Zepto with core and event modules.
https://github.com/jaydenseric/Purty-Picker
*/
// DOM ready
$(function() {
'use strict';
//-------------------------------------------- Color conversions
//---------------------- Convert HSL to RGB
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
function HSLToRGB(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
var r, g, b;
if(s == 0) {
r = g = b = l; // Achromatic
} else {
var hueToRGB = function(p, q, t) {
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
p = 2 * l - q;
r = hueToRGB(p, q, h + 1/3);
g = hueToRGB(p, q, h);
b = hueToRGB(p, q, h - 1/3);
}
return {
red: Math.round(r * 255),
green: Math.round(g * 255),
blue: Math.round(b * 255)
};
}
//---------------------- Convert RGB to HSL
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
function RGBToHSL(r, g, b) {
r /= 255,
g /= 255,
b /= 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // Achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
hue: Math.round(h * 360),
saturation: Math.round(s * 100),
luminosity: Math.round(l * 100)
};
}
//---------------------- Convert RGB to Hex
// Source: http://stackoverflow.com/a/5624139
function RGBToHex(r, g, b) {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
//---------------------- Convert hex to RGB
// Source: http://stackoverflow.com/a/11508164
function hexToRGB(hex) {
var bigInt = parseInt(hex.replace('#', ''), 16),
r = (bigInt >> 16) & 255,
g = (bigInt >> 8) & 255,
b = bigInt & 255;
return {
red: r,
green: g,
blue: b
};
}
//---------------------- Convert hex to HSL
function hexToHSL(hex) {
var RGB = hexToRGB(hex);
return RGBToHSL(RGB.red, RGB.green, RGB.blue);
}
//---------------------- Convert HSL to hex
function HSLToHex(h, s, l) {
var RGB = HSLToRGB(h, s, l);
return RGBToHex(RGB.red, RGB.green, RGB.blue);
}
//-------------------------------------------- Setup each color picker
$.each($('.color-picker'), function() {
//---------------------- Find componenets
var picker = $(this),
formatInput = picker.find('.format'),
colorInput = picker.find('.color'),
luminosityInput = picker.find('input[type=range]'),
spectrum = picker.find('.spectrum'),
pin = picker.find('.pin');
//---------------------- Get current color in HSL
function getHSL() {
var position = picker.find('.pin').position(),
width = spectrum.width(),
height = spectrum.height();
return {
hue: Math.round(position.left / width * 360),
saturation: Math.round(position.top / height * 100),
luminosity: luminosityInput.val()
};
}
//---------------------- Output color in desired format
function updateColorInput() {
var HSL = getHSL();
switch (formatInput.val()) {
case 'HSL':
colorInput.val('hsl(' + HSL.hue + ', ' + HSL.saturation + '%, ' + HSL.luminosity + '%)');
break;
case 'RGB':
var RGB = HSLToRGB(HSL.hue, HSL.saturation, HSL.luminosity);
colorInput.val('rgb(' + RGB.red + ', ' + RGB.green + ', ' + RGB.blue + ')');
break;
case 'Hex':
colorInput.val(HSLToHex(HSL.hue, HSL.saturation, HSL.luminosity));
break;
}
// Trigger color picker change event for custom callbacks
picker.trigger('change');
}
//---------------------- Set color format
formatInput.on('change', function() {
updateColorInput();
});
//---------------------- Set color
colorInput.on('change', function() {
// Get the color values in HSL format
var HSL;
switch (formatInput.val()) {
case 'HSL':
var values = $(this).val().match(/\d+/g);
HSL = {
hue: values[0],
saturation: values[1],
luminosity: values[2]
};
break;
case 'RGB':
var values = $(this).val().match(/\d+/g);
HSL = RGBToHSL(values[0], values[1], values[2]);
break;
case 'Hex':
HSL = hexToHSL($(this).val());
break;
}
// Set the luminosity
luminosityInput.val(HSL.luminosity);
setLuminosity(HSL.luminosity);
// Place the pin
pin.css({
left: HSL.hue / 360 * 100 + '%',
top: HSL.saturation + '%'
});
// Trigger color picker change event for custom callbacks
picker.trigger('change');
});
//---------------------- Set luminosity
//---------- Set the luminosity spectrum overlay
function setLuminosity(luminosity) {
var color,
alpha;
if (luminosity <= 50) {
color = '0, 0, 0';
alpha = 1 - luminosity / 100 * 2;
} else {
color = '255, 255, 255';
alpha = luminosity / 100 * 2 - 1;
}
// Apply luminosity to the spectrum
spectrum.children().css('background-color', 'rgba(' + color + ', ' + alpha + ')');
}
//---------- Luminosity input interaction
luminosityInput.on('change', function() {
setLuminosity($(this).val());
updateColorInput();
});
//---------------------- Set hue, saturation via pin
//---------- Move the pin
var movePin = function(event) {
var offset = spectrum.offset(),
width = spectrum.width(),
height = spectrum.height(),
x = event.changedTouches[0].clientX - offset.left,
y = event.changedTouches[0].clientY - offset.top;
// Account for pin being dragged outside the spectrum area
// Sanatize x
if (x < 0) {
x = 0;
} else if (x >= width) {
x = width;
}
// Sanatize y
if (y < 0) {
y = 0;
} else if (y >= height) {
y = height;
}
// Place the pin
pin.css({
left: x / width * 100 + '%',
top: y / height * 100 + '%'
});
// Output new color value
updateColorInput();
};
//---------- Pin interaction
spectrum.on('touchstart', function(event) {
event.preventDefault();
movePin(event);
spectrum.addClass('active');
$(document).on('touchmove', movePin);
});
$(document).on('touchend', function() {
spectrum.removeClass('active');
$(document).off('touchmove', movePin);
});
spectrum.on('touchmove touchstart', movePin);
//---------------------- Output color preview
picker.on('change', function() {
colorInput.css('background-color', colorInput.val()).toggleClass('dark', luminosityInput.val() <= 50);
});
//---------------------- Initialize this color picker
colorInput.trigger('change');
});
});

View File

@ -0,0 +1,289 @@
/*
Purty Picker Copyright 2013 Jayden Seric (MIT license).
A super lightweight visual HSL, RGB and hex color picker with a responsive, touch-friendly and customizable UI.
Requires jQuery or Zepto with core and event modules.
https://github.com/jaydenseric/Purty-Picker
*/
// DOM ready
$(function() {
'use strict';
//-------------------------------------------- Color conversions
//---------------------- Convert HSL to RGB
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
function HSLToRGB(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
var r, g, b;
if(s == 0) {
r = g = b = l; // Achromatic
} else {
var hueToRGB = function(p, q, t) {
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
p = 2 * l - q;
r = hueToRGB(p, q, h + 1/3);
g = hueToRGB(p, q, h);
b = hueToRGB(p, q, h - 1/3);
}
return {
red: Math.round(r * 255),
green: Math.round(g * 255),
blue: Math.round(b * 255)
};
}
//---------------------- Convert RGB to HSL
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
function RGBToHSL(r, g, b) {
r /= 255,
g /= 255,
b /= 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // Achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
hue: Math.round(h * 360),
saturation: Math.round(s * 100),
luminosity: Math.round(l * 100)
};
}
//---------------------- Convert RGB to Hex
// Source: http://stackoverflow.com/a/5624139
function RGBToHex(r, g, b) {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
//---------------------- Convert hex to RGB
// Source: http://stackoverflow.com/a/11508164
function hexToRGB(hex) {
var bigInt = parseInt(hex.replace('#', ''), 16),
r = (bigInt >> 16) & 255,
g = (bigInt >> 8) & 255,
b = bigInt & 255;
return {
red: r,
green: g,
blue: b
};
}
//---------------------- Convert hex to HSL
function hexToHSL(hex) {
var RGB = hexToRGB(hex);
return RGBToHSL(RGB.red, RGB.green, RGB.blue);
}
//---------------------- Convert HSL to hex
function HSLToHex(h, s, l) {
var RGB = HSLToRGB(h, s, l);
return RGBToHex(RGB.red, RGB.green, RGB.blue);
}
//-------------------------------------------- Setup each color picker
$.each($('.color-picker'), function() {
//---------------------- Find componenets
var picker = $(this),
formatInput = picker.find('.format'),
colorInput = picker.find('.color'),
luminosityInput = picker.find('input[type=range]'),
spectrum = picker.find('.spectrum'),
pin = picker.find('.pin');
//---------------------- Get current color in HSL
function getHSL() {
var position = picker.find('.pin').position(),
width = spectrum.width(),
height = spectrum.height();
return {
hue: Math.round(position.left / width * 360),
saturation: Math.round(position.top / height * 100),
luminosity: luminosityInput.val()
};
}
//---------------------- Output color in desired format
function updateColorInput() {
var HSL = getHSL();
switch (formatInput.val()) {
case 'HSL':
colorInput.val('hsl(' + HSL.hue + ', ' + HSL.saturation + '%, ' + HSL.luminosity + '%)');
break;
case 'RGB':
var RGB = HSLToRGB(HSL.hue, HSL.saturation, HSL.luminosity);
colorInput.val('rgb(' + RGB.red + ', ' + RGB.green + ', ' + RGB.blue + ')');
break;
case 'Hex':
colorInput.val(HSLToHex(HSL.hue, HSL.saturation, HSL.luminosity));
break;
}
// Trigger color picker change event for custom callbacks
picker.trigger('change');
}
//---------------------- Set color format
formatInput.on('change', function() {
updateColorInput();
});
//---------------------- Set color
colorInput.on('change', function() {
// Get the color values in HSL format
var HSL;
switch (formatInput.val()) {
case 'HSL':
var values = $(this).val().match(/\d+/g);
HSL = {
hue: values[0],
saturation: values[1],
luminosity: values[2]
};
break;
case 'RGB':
var values = $(this).val().match(/\d+/g);
HSL = RGBToHSL(values[0], values[1], values[2]);
break;
case 'Hex':
HSL = hexToHSL($(this).val());
break;
}
// Set the luminosity
luminosityInput.val(HSL.luminosity);
setLuminosity(HSL.luminosity);
// Place the pin
pin.css({
left: HSL.hue / 360 * 100 + '%',
top: HSL.saturation + '%'
});
// Trigger color picker change event for custom callbacks
picker.trigger('change');
});
//---------------------- Set luminosity
//---------- Set the luminosity spectrum overlay
function setLuminosity(luminosity) {
var color,
alpha;
if (luminosity <= 50) {
color = '0, 0, 0';
alpha = 1 - luminosity / 100 * 2;
} else {
color = '255, 255, 255';
alpha = luminosity / 100 * 2 - 1;
}
// Apply luminosity to the spectrum
spectrum.children().css('background-color', 'rgba(' + color + ', ' + alpha + ')');
}
//---------- Luminosity input interaction
luminosityInput.on('change', function() {
setLuminosity($(this).val());
updateColorInput();
});
//---------------------- Set hue, saturation via pin
//---------- Move the pin
var movePin = function(event) {
var offset = spectrum.offset(),
width = spectrum.width(),
height = spectrum.height(),
x = event.clientX - offset.left,
y = event.clientY - offset.top;
// Account for pin being dragged outside the spectrum area
// Sanatize x
if (x < 0) {
x = 0;
} else if (x >= width) {
x = width;
}
// Sanatize y
if (y < 0) {
y = 0;
} else if (y >= height) {
y = height;
}
// Place the pin
pin.css({
left: x / width * 100 + '%',
top: y / height * 100 + '%'
});
// Output new color value
updateColorInput();
};
//---------- Pin interaction
spectrum.on('mousedown', function(event) {
event.preventDefault();
movePin(event);
spectrum.addClass('active');
$(document).on('mousemove', movePin);
});
$(document).on('mouseup', function() {
spectrum.removeClass('active');
$(document).off('mousemove', movePin);
});
spectrum.on('touchmove touchstart', movePin);
//---------------------- Output color preview
picker.on('change', function() {
colorInput.css('background-color', colorInput.val()).toggleClass('dark', luminosityInput.val() <= 50);
});
//---------------------- Initialize this color picker
colorInput.trigger('change');
});
});

View File

@ -0,0 +1 @@
(function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))window.mobile=true})(navigator.userAgent||navigator.vendor||window.opera,'http://detectmobilebrowser.com/mobile');

22
Mobile/js/libs/stack.js Normal file
View File

@ -0,0 +1,22 @@
// Zepto.js
// (c) 2010-2014 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
;(function($){
$.fn.end = function(){
return this.prevObject || $()
}
$.fn.andSelf = function(){
return this.add(this.prevObject || $())
}
'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){
var fn = $.fn[property]
$.fn[property] = function(){
var ret = fn.apply(this, arguments)
ret.prevObject = this
return ret
}
})
})(Zepto)

166
Mobile/js/libs/touch.js Normal file
View File

@ -0,0 +1,166 @@
// Zepto.js
// (c) 2010-2014 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
;(function($){
var touch = {},
touchTimeout, tapTimeout, swipeTimeout, longTapTimeout,
longTapDelay = 750,
gesture
function swipeDirection(x1, x2, y1, y2) {
return Math.abs(x1 - x2) >=
Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
}
function longTap() {
longTapTimeout = null
if (touch.last) {
touch.el.trigger('longTap')
window.touchEl = touch.el;
touch = {}
}
}
function cancelLongTap() {
if (longTapTimeout) clearTimeout(longTapTimeout)
longTapTimeout = null
}
function cancelAll() {
if (touchTimeout) clearTimeout(touchTimeout)
if (tapTimeout) clearTimeout(tapTimeout)
if (swipeTimeout) clearTimeout(swipeTimeout)
if (longTapTimeout) clearTimeout(longTapTimeout)
touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
touch = {}
}
function isPrimaryTouch(event){
return (event.pointerType == 'touch' ||
event.pointerType == event.MSPOINTER_TYPE_TOUCH)
&& event.isPrimary
}
function isPointerEventType(e, type){
return (e.type == 'pointer'+type ||
e.type.toLowerCase() == 'mspointer'+type)
}
$(document).ready(function(){
var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType
if ('MSGesture' in window) {
gesture = new MSGesture()
gesture.target = document.body
}
$(document)
.bind('MSGestureEnd', function(e){
var swipeDirectionFromVelocity =
e.velocityX > 1 ? 'Right' : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null;
if (swipeDirectionFromVelocity) {
touch.el.trigger('swipe')
touch.el.trigger('swipe'+ swipeDirectionFromVelocity)
}
})
.on('touchstart MSPointerDown pointerdown', function(e){
if((_isPointerType = isPointerEventType(e, 'down')) &&
!isPrimaryTouch(e)) return
firstTouch = _isPointerType ? e : e.touches[0]
if (e.touches && e.touches.length === 1 && touch.x2) {
// Clear out touch movement data if we have it sticking around
// This can occur if touchcancel doesn't fire due to preventDefault, etc.
touch.x2 = undefined
touch.y2 = undefined
}
now = Date.now()
delta = now - (touch.last || now)
touch.el = $('tagName' in firstTouch.target ?
firstTouch.target : firstTouch.target.parentNode)
touchTimeout && clearTimeout(touchTimeout)
touch.x1 = firstTouch.pageX
touch.y1 = firstTouch.pageY
if (delta > 0 && delta <= 250) touch.isDoubleTap = true
touch.last = now
longTapTimeout = setTimeout(longTap, longTapDelay)
// adds the current touch contact for IE gesture recognition
if (gesture && _isPointerType) gesture.addPointer(e.pointerId);
})
.on('touchmove MSPointerMove pointermove', function(e){
if((_isPointerType = isPointerEventType(e, 'move')) &&
!isPrimaryTouch(e)) return
firstTouch = _isPointerType ? e : e.touches[0]
if( $.moveCancel ) cancelLongTap()
touch.x2 = firstTouch.pageX
touch.y2 = firstTouch.pageY
deltaX += Math.abs(touch.x1 - touch.x2)
deltaY += Math.abs(touch.y1 - touch.y2)
})
.on('touchend MSPointerUp pointerup', function(e){
if((_isPointerType = isPointerEventType(e, 'up')) &&
!isPrimaryTouch(e)) return
cancelLongTap()
// swipe
if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
(touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
swipeTimeout = setTimeout(function() {
touch.el.trigger('swipe')
touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
touch = {}
}, 0)
// normal tap
else if ('last' in touch)
// don't fire tap when delta position changed by more than 30 pixels,
// for instance when moving to a point and back to origin
if (deltaX < 30 && deltaY < 30) {
// delay by one tick so we can cancel the 'tap' event if 'scroll' fires
// ('tap' fires before 'scroll')
tapTimeout = setTimeout(function() {
// trigger universal 'tap' with the option to cancelTouch()
// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
var event = $.Event('tap')
event.cancelTouch = cancelAll
touch.el.trigger(event)
// trigger double tap immediately
if (touch.isDoubleTap) {
if (touch.el) touch.el.trigger('doubleTap')
touch = {}
}
// trigger single tap after 250ms of inactivity
else {
touchTimeout = setTimeout(function(){
touchTimeout = null
if (touch.el) touch.el.trigger('singleTap')
touch = {}
}, 250)
}
}, 0)
} else {
touch = {}
}
deltaX = deltaY = 0
})
// when the browser window loses focus,
// for example when a modal dialog is shown,
// cancel all ongoing events
.on('touchcancel MSPointerCancel pointercancel', cancelAll)
// scrolling the window indicates intention of the user
// to scroll, not tap or swipe, so cancel all ongoing events
$(window).on('scroll', cancelAll)
})
;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown',
'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){
$.fn[eventName] = function(callback){ return this.on(eventName, callback) }
})
})(Zepto)

2
Mobile/js/libs/yepnope.min.js vendored Normal file
View File

@ -0,0 +1,2 @@
/*yepnope1.5.x|WTFPL*/
(function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}})(this,document);

2
Mobile/js/libs/zepto.min.js vendored Normal file

File diff suppressed because one or more lines are too long

38
Mobile/js/main.js Normal file
View File

@ -0,0 +1,38 @@
"use strict";
$(document).ready(function() {
window.c = $('canvas')[0].getContext('2d');
window.o = $('canvas')[1].getContext('2d');
window.settings = {
lineWidth : 2,
color : 'black',
type: 'sketch',
lineCap: 'round',
lineJoin: 'round',
furLength: 5,
connectTelorance: 40,
composite: 'source-over'
};
window.points = [];
window.$c = $('canvas');
window.points.history = [{ data: c.createImageData($c.width(), $c.height()), points: []}];
window.points.history.last = 0;
sizeAndPos();
//$(window).resize(sizeAndPos);
$('.color-picker').change(function() {
var c = $(this).find('.color').val();
settings.color = c;
$('#setcolor span').html(c);
})
$('.color').val('#000000');
/*yepnope({
test: window.mobile,
yep : ['js/libs/touch.js', 'js/mobile.js', 'js/libs/color-picker-touch.js'],
nope: ['js/desktop.js', 'js/libs/color-picker.js']
})*/
})

223
Mobile/js/mobile.js Normal file
View File

@ -0,0 +1,223 @@
"use strict";
$(document).ready(function() {
// Open External Links in browser
$('*').click(function(e) {
e.preventDefault();
})
$('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
}
})
})
function save() {
switch(save.background) {
case 'white': {
var cache = {
fillStyle: c.color,
composite: c.globalCompositeOperation
}
c.fillStyle = 'white';
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = cache.fillStyle;
c.globalCompositeOperation = cache.composite;
break;
}
case 'current color': {
var cache = {
fillStyle: c.color,
composite: c.globalCompositeOperation
}
c.fillStyle = settings.strokeStyle;
c.globalCompositeOperation = 'destination-over';
c.fillRect(0, 0, width(), height());
c.fillStyle = cache.fillStyle;
c.globalCompositeOperation = cache.composite;
break;
}
}
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')
console.warn(this.error);
}
c.putImageData(window.points.history[window.points.history.last].data, 0, 0);
}
$('.menu').tap(function() {
$('#menu').toggleClass('pulled');
})
$('.save').tap(function() {
$('#save').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;
points[points.length-1].type = '';
points[points.length-1].start = undefined;
}
})
// 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.find('button').tap(function(e) {
e.preventDefault();
$(this).parents('form').addClass('hidden');
})
// Confirm
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;
}
})
$(this).parents('form').addClass('hidden');
window[v]();
})
$confirm.find('button').first().tap(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');
})
})
// 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);
}
}
}).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;
})
$('#undo').tap(undo);
$('#redo').tap(redo);
$('#about').tap(function() {
$('.about').removeClass('hidden');
})
});