diff --git a/css/color-picker.css b/css/color-picker.css new file mode 100644 index 0000000..cfcbba5 --- /dev/null +++ b/css/color-picker.css @@ -0,0 +1,90 @@ +/* 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(gray, transparent), linear-gradient(90deg, red, #ff2b00, #ff5500, #ff8000, #ffaa00, #ffd500, yellow, #d4ff00, #aaff00, #80ff00, #55ff00, #2bff00, lime, #00ff2b, #00ff55, #00ff80, #00ffaa, #00ffd5, cyan, #00d4ff, #00aaff, #007fff, #0055ff, #002bff, blue, #2a00ff, #5500ff, #7f00ff, #aa00ff, #d400ff, magenta, #ff00d4, #ff00aa, #ff0080, #ff0055, #ff002b, red); + -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; +} diff --git a/css/imgs/clear.png b/css/imgs/clear.png new file mode 100644 index 0000000..cfcff2e Binary files /dev/null and b/css/imgs/clear.png differ diff --git a/css/imgs/redo.png b/css/imgs/redo.png new file mode 100644 index 0000000..d2864fb Binary files /dev/null and b/css/imgs/redo.png differ diff --git a/css/imgs/undo.png b/css/imgs/undo.png new file mode 100644 index 0000000..6117001 Binary files /dev/null and b/css/imgs/undo.png differ diff --git a/css/main.less b/css/main.less index 75e4be2..4cf4ec5 100644 --- a/css/main.less +++ b/css/main.less @@ -65,7 +65,25 @@ button { border: none; } +.picker { + width: 30rem; + height: 30rem; + position: absolute; + left: 50%; + top: 50%; + margin-top: -15rem; + margin-left: -15rem; + #closePicker { + width: 2rem; + height: 2rem; + border: 1px solid rgb(227, 227, 227); + border-radius: 50%; + position: absolute; + top: 1rem; + left: 27rem; + } +} header { @@ -117,12 +135,14 @@ header { color: white; font-family: 'MozTT-Light'; font-size: 8pt; + transition: left 0.2s ease-out; &.pulled { left: 0; + transition: left 0.2s ease-out; } - button[id^='set'], p { + button[id^='set'], p, .bottom button { background: none; display: block; width: 75%; @@ -132,6 +152,7 @@ header { font-family: 'MozTT-Light'; font-size: 8pt; padding: 0 0.6rem; + cursor: pointer; } span { float: right; @@ -150,13 +171,22 @@ header { } } } - .icon-settings { + hr { + clear: both; + padding: 0.7rem 0; + margin-bottom: 0.7rem; + border: none; + border-bottom: 1px solid rgba(255,255,255,0.3); + } + *[class^='icon'] { display: block; margin: 1rem 0.5rem; + &:nth-of-type(2) { + padding-top: 0.5rem; + } &:before { content: ''; - background: url('imgs/settings.png') center center no-repeat; background-size: 2rem; width: 2rem; height: 2rem; @@ -166,10 +196,30 @@ header { } } + .icon-settings:before { + background-image: url('imgs/settings.png'); + } + .icon-clear:before { + background-image: url('imgs/clear.png'); + } + .icon-undo:before { + background-image: url('imgs/undo.png'); + } + .icon-redo:before { + background-image: url('imgs/redo.png'); + } + .options { display: block; margin-top: 1rem; } + .bottom { + position: absolute; + bottom: 5rem; + button { + margin-left: 3.5rem; + } + } } diff --git a/css/value_selector.css b/css/value_selector.css index aebc7a7..0a3493c 100644 --- a/css/value_selector.css +++ b/css/value_selector.css @@ -114,7 +114,7 @@ form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label } /* Checked status */ -form[role="dialog"][data-type="value-selector"] [role="listbox"] li[aria-selected="true"] span { +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; diff --git a/index.html b/index.html index ba294b7..34be387 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,7 @@ + @@ -36,24 +37,59 @@

Line Width 2

-
+
- - + +
+
+
+
+

Sketch

+

Connet Telorance40

+
+
+ + +
+
+
+ + + +
+ + +
- - - + + + + + + + diff --git a/js/events.js b/js/events.js index 0326d4b..f910013 100644 --- a/js/events.js +++ b/js/events.js @@ -1,22 +1,56 @@ +"use strict"; + +function save() { + switch(save.background) { + case 'white': { + var cache = { + color: c.color, + composite: c.globalCompositeOperation + } + c.fillStyle = 'white'; + c.globalCompositeOperation = 'destination-over'; + c.fillRect(0, 0, $c.width(), $c.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, $c.width(), $c.height()); + c.fillStyle = cache.fillStyle; + c.globalCompositeOperation = cache.composite; + break; + } + } + var data = $c[0].toDataURL(); + window.open(data, save['file name']); + + c.putImageData(window.points.history[window.points.history.length-1].data, 0, 0); + +} + $('.menu').click(function() { $('#menu').toggleClass('pulled'); }) $('.save').click(function() { - var data = $c[0].toDataURL(); - var img = $(''); - $('body').append(img); + $('#save').removeClass('hidden'); }) - $c.last().bind('mousedown', function(e) { + $c.last().on('mousedown', function(e) { e.preventDefault(); var xy = relative(e.pageX, e.pageY); startPoint(xy.x, xy.y); window.active = true; - }).bind('mousemove', function(e) { + }).on('mousemove', function(e) { e.preventDefault(); if (!window.active || settings.type == 'line') return; var xy = relative(e.pageX, e.pageY); drawPoint(xy.x, xy.y); - }).bind('mouseup mouseout', function(e) { + }).on('mouseup', function(e) { e.preventDefault(); window.active = false; @@ -33,32 +67,68 @@ // Value Selector - var $selector = $('form[data-type="value-selector"]'); + // Single + + var $single = $('form[data-type="value-selector"].single'); - $selector.find('li').on('mouseup', function(e) { - alert(e.type); - $(this).parent().find('li').removeAttr('aria-selected'); + $single.find('li').click(function(e) { + $(this).parent().find('li[aria-selected]').removeAttr('aria-selected'); $(this).attr('aria-selected', 'true'); - var prop = $(this).parents('form').attr('id'), - key = $(this).find('label span').html().toLowerCase(); - window.settings[prop] = key; + var key = $(this).parents('form').attr('id'), + value = $(this).find('label span').html().toLowerCase(); + window.settings[key] = value; - $('button[id="set' + prop + '"] span').html(key[0].toUpperCase() + key.substr(1)); + $('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'); }) - - $selector.submit(function(e) { + $single.submit(function(e) { e.preventDefault(); $(this).addClass('hidden'); }) + // Confirm + + var $confirm = $('form[data-type="value-selector"].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(); + if( key !== 'file name' ) value = key.toLowerCase(); + + window[v][key] = value; + } + }) + $(this).parents('form').addClass('hidden'); + window[v](); + }) + $confirm.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]; - $(this).on('mouseup', function(e) { + // Exception for Color + if( target == 'color' ) { + return $(this).click(function() { + $('.picker').removeClass('hidden'); + }) + } + $(this).click(function(e) { e.preventDefault(); $('form[id="' + target + '"]').removeClass('hidden'); }) @@ -66,19 +136,50 @@ // Seekbar - var sliderLeft = $('div[role="slider"] button').offset().left; + var sliderLeft; $('div[role="slider"] button').on('mousedown', function() { $(this).attr('data-moving','true'); + if( !sliderLeft ) sliderLeft = $('div[role="slider"] button').offset().left; }).on('mousemove', function(e) { if( $(this).attr('data-moving') ) { - var x = e.pageX - sliderLeft - 15; - if( x <= 100 && x > 0 ) { + var x = parseInt(e.pageX - sliderLeft - 15); + var progress = $(this).parent().children().first(); + var max = +progress.attr('max'); + var min = +progress.attr('min'); + if( x <= max && x >= min ) { $(this).css('left', x+'%'); $(this).parent().find('progress').attr('value', x); - settings.lineWidth = x / 10; - $('#lineWidth span').html(x); + var key = $(this).parents('div[role="slider"]').attr('class'); + settings[key] = x; + $('#'+ key +' span').html(x); } } }).on('mouseup mouseleave', function() { $(this).removeAttr('data-moving'); }) + + + // Color Picker + + $('#closePicker').click(function() { + $('.picker').addClass('hidden'); + }) + + // Bottom + + $('#clear').click(function() { + c.clearRect(0, 0, $c.width(), $c.height()); + 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, $c.width(), $c.height()), + points: [] + }) + window.points.history.last = window.points.history.length-1; + }) + + $('#undo').click(undo); + $('#redo').click(redo); + diff --git a/js/functions.js b/js/functions.js index dfebb71..4c48306 100644 --- a/js/functions.js +++ b/js/functions.js @@ -6,16 +6,20 @@ function sizeAndPos() { var data = c.getImageData(0,0, $c.width(), $c.height()); var w = $(window).width(), h = $(window).height(); - $c.attr('width', w); - $c.attr('height',h - 53); + $c.attr('width', w * window.devicePixelRatio); + $c.attr('height',h * window.devicePixelRatio - 53 * window.devicePixelRatio); + $c.css({ + 'width' : w, + 'height' : h - 53 + }); c.clearRect(0,0, $c.width(), $c.height()); c.putImageData(data, 0, 0); } function relative(x,y) { return { - x : x - $c.offset().left, - y : y - $c.offset().top + x : x*window.devicePixelRatio, + y : y*window.devicePixelRatio - 53 * window.devicePixelRatio } } @@ -32,11 +36,13 @@ function line(x1, y1, x2, y2, opts, overlay) { c.beginPath(); c.lineCap = opts.lineCap || settings.lineCap; c.lineJoin = opts.lineJoin || settings.lineJoin; - c.strokeStyle = opts.strokeStyle || settings.strokeStyle; - c.lineWidth = opts.lineWidth || settings.lineWidth; + 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); - c.stroke(); + if( !opts.noStroke ) c.stroke(); + if( opts.fill ) c.fill(); } function erase(x1, y1, x2, y2, overlay) { @@ -73,6 +79,13 @@ function redo() { } } +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 ***/ @@ -90,7 +103,10 @@ function startPoint(x, y) { type : settings.type } if( old.type !== 'line' && current.type == 'line' ) { - line(x,y,x,y, {lineWidth: 5, strokeStyle: 'red'}, true); + window.o.beginPath(); + window.o.fillStyle = 'red'; + window.o.arc(x,y, 3, 0, 2*Math.PI); + window.o.fill(); } if( old.type == 'line' ) { @@ -135,11 +151,11 @@ function drawPoint(x,y) { 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, 40)) { + 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; - line(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/2}) + line(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; @@ -155,10 +171,10 @@ function drawPoint(x,y) { 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.lineWidth*20)) { + 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 || 0.2; + var l = settings.furLength / 100 || 0.2; line(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}) } } diff --git a/js/libs/color-picker-touch.js b/js/libs/color-picker-touch.js new file mode 100644 index 0000000..85acba3 --- /dev/null +++ b/js/libs/color-picker-touch.js @@ -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'); + + }); +}); diff --git a/js/libs/color-picker.js b/js/libs/color-picker.js new file mode 100644 index 0000000..7c211f9 --- /dev/null +++ b/js/libs/color-picker.js @@ -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'); + }); +}); diff --git a/js/libs/stack.js b/js/libs/stack.js new file mode 100644 index 0000000..cbec614 --- /dev/null +++ b/js/libs/stack.js @@ -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) diff --git a/js/libs/touch.js b/js/libs/touch.js new file mode 100644 index 0000000..c449212 --- /dev/null +++ b/js/libs/touch.js @@ -0,0 +1,165 @@ +// 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') + 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] + 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) diff --git a/js/libs/zepto.min.js b/js/libs/zepto.min.js index 112a1da..f64fc04 100644 --- a/js/libs/zepto.min.js +++ b/js/libs/zepto.min.js @@ -1,2 +1,2 @@ -/* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ -(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) \ No newline at end of file +/* Zepto v1.1.2 - zepto event ajax form ie - zeptojs.com/license */ +var Zepto=function(){function G(a){return a==null?String(a):z[A.call(a)]||"object"}function H(a){return G(a)=="function"}function I(a){return a!=null&&a==a.window}function J(a){return a!=null&&a.nodeType==a.DOCUMENT_NODE}function K(a){return G(a)=="object"}function L(a){return K(a)&&!I(a)&&Object.getPrototypeOf(a)==Object.prototype}function M(a){return a instanceof Array}function N(a){return typeof a.length=="number"}function O(a){return g.call(a,function(a){return a!=null})}function P(a){return a.length>0?c.fn.concat.apply([],a):a}function Q(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function R(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function S(a,b){return typeof b=="number"&&!k[Q(a)]?b+"px":b}function T(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=getComputedStyle(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function U(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function V(c,d,e){for(b in d)e&&(L(d[b])||M(d[b]))?(L(d[b])&&!L(c[b])&&(c[b]={}),M(d[b])&&!M(c[b])&&(c[b]=[]),V(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function W(a,b){return b==null?c(a):c(a).filter(b)}function X(a,b,c,d){return H(b)?b.call(a,c,d):b}function Y(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function Z(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function $(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:!/^0/.test(a)&&!isNaN(b=Number(a))?b:/^[\[\{]/.test(a)?c.parseJSON(a):a):a}catch(d){return a}}function _(a,b){b(a);for(var c in a.childNodes)_(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,m=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=/([A-Z])/g,q=["val","css","html","text","data","width","height","offset"],r=["after","prepend","before","append"],s=h.createElement("table"),t=h.createElement("tr"),u={tr:h.createElement("tbody"),tbody:s,thead:s,tfoot:s,td:t,th:t,"*":h.createElement("div")},v=/complete|loaded|interactive/,w=/^\.([\w-]+)$/,x=/^#([\w-]*)$/,y=/^[\w-]*$/,z={},A=z.toString,B={},C,D,E=h.createElement("div"),F={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"};return B.matches=function(a,b){if(!b||!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=E).appendChild(a),d=~B.qsa(e,b).indexOf(a),f&&E.removeChild(a),d},C=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},D=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},B.fragment=function(b,d,e){var g,i,j;return m.test(b)&&(g=c(h.createElement(RegExp.$1))),g||(b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=l.test(b)&&RegExp.$1),d in u||(d="*"),j=u[d],j.innerHTML=""+b,g=c.each(f.call(j.childNodes),function(){j.removeChild(this)})),L(e)&&(i=c(g),c.each(e,function(a,b){q.indexOf(a)>-1?i[a](b):i.attr(a,b)})),g},B.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},B.isZ=function(a){return a instanceof B.Z},B.init=function(b,d){var e;if(!b)return B.Z();if(typeof b=="string"){b=b.trim();if(b[0]=="<"&&l.test(b))e=B.fragment(b,RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=B.qsa(h,b)}}else{if(H(b))return c(h).ready(b);if(B.isZ(b))return b;if(M(b))e=O(b);else if(K(b))e=[b],b=null;else if(l.test(b))e=B.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=B.qsa(h,b)}}return B.Z(e,b)},c=function(a,b){return B.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){V(a,c,b)}),a},B.qsa=function(a,b){var c,d=b[0]=="#",e=!d&&b[0]==".",g=d||e?b.slice(1):b,h=y.test(g);return J(a)&&h&&d?(c=a.getElementById(g))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(h&&!d?e?a.getElementsByClassName(g):a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=G,c.isFunction=H,c.isWindow=I,c.isArray=M,c.isPlainObject=L,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=C,c.trim=function(a){return a==null?"":String.prototype.trim.call(a)},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(N(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return H(a)?this.not(this.not(a)):c(g.call(this,function(b){return B.matches(b,a)}))},add:function(a,b){return c(D(this.concat(c(a,b))))},is:function(a){return this.length>0&&B.matches(this[0],a)},not:function(b){var d=[];if(H(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):N(b)&&H(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return K(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!K(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!K(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(B.qsa(this[0],a)):b=this.map(function(){return B.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:B.matches(d,a)))d=d!==b&&!J(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!J(a)&&b.indexOf(a)<0)return b.push(a),a});return W(b,a)},parent:function(a){return W(D(this.pluck("parentNode")),a)},children:function(a){return W(this.map(function(){return U(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return W(this.map(function(a,b){return g.call(U(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=""),getComputedStyle(this,"").getPropertyValue("display")=="none"&&(this.style.display=T(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=H(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=H(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(a){return arguments.length===0?this.length>0?this[0].innerHTML:null:this.each(function(b){var d=this.innerHTML;c(this).empty().append(X(this,a,b,d))})},text:function(b){return arguments.length===0?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b===a?"":""+b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(K(c))for(b in c)Y(this,b,c[b]);else Y(this,c,X(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&Y(this,a)})},prop:function(b,c){return b=F[b]||b,c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=X(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+b.replace(p,"-$1").toLowerCase(),c);return d!==null?$(d):a},val:function(a){return arguments.length===0?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value):this.each(function(b){this.value=X(this,a,b,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=X(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,d){if(arguments.length<2){var e=this[0],f=getComputedStyle(e,"");if(!e)return;if(typeof a=="string")return e.style[C(a)]||f.getPropertyValue(a);if(M(a)){var g={};return c.each(M(a)?a:[a],function(a,b){g[b]=e.style[C(b)]||f.getPropertyValue(b)}),g}}var h="";if(G(a)=="string")!d&&d!==0?this.each(function(){this.style.removeProperty(Q(a))}):h=Q(a)+":"+S(a,d);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(Q(b))}):h+=Q(b)+":"+S(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+h})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return a?e.some.call(this,function(a){return this.test(Z(a))},R(a)):!1},addClass:function(a){return a?this.each(function(b){d=[];var e=Z(this),f=X(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&Z(this,e+(e?" ":"")+d.join(" "))}):this},removeClass:function(b){return this.each(function(c){if(b===a)return Z(this,"");d=Z(this),X(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(R(a)," ")}),Z(this,d.trim())})},toggleClass:function(b,d){return b?this.each(function(e){var f=c(this),g=X(this,b,e,Z(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})}):this},scrollTop:function(b){if(!this.length)return;var c="scrollTop"in this[0];return b===a?c?this[0].scrollTop:this[0].pageYOffset:this.each(c?function(){this.scrollTop=b}:function(){this.scrollTo(this.scrollX,b)})},scrollLeft:function(b){if(!this.length)return;var c="scrollLeft"in this[0];return b===a?c?this[0].scrollLeft:this[0].pageXOffset:this.each(c?function(){this.scrollLeft=b}:function(){this.scrollTo(b,this.scrollY)})},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){var d=b.replace(/./,function(a){return a[0].toUpperCase()});c.fn[b]=function(e){var f,g=this[0];return e===a?I(g)?g["inner"+d]:J(g)?g.documentElement["scroll"+d]:(f=this.offset())&&f[b]:this.each(function(a){g=c(this),g.css(b,X(this,e,a,g[b]()))})}}),r.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=G(b),a=="object"||a=="array"||b==null?b:B.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();_(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),B.Z.prototype=c.fn,B.uniq=D,B.deserializeValue=$,c.zepto=B,c}();window.Zepto=Zepto,window.$===undefined&&(window.$=Zepto),function(a){function m(a){return a._zid||(a._zid=c++)}function n(a,b,c,d){b=o(b);if(b.ns)var e=p(b.ns);return(h[m(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||e.test(a.ns))&&(!c||m(a.fn)===m(c))&&(!d||a.sel==d)})}function o(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function p(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function q(a,b){return a.del&&!j&&a.e in k||!!b}function r(a){return l[a]||j&&k[a]||a}function s(b,c,e,f,g,i,j){var k=m(b),n=h[k]||(h[k]=[]);c.split(/\s/).forEach(function(c){if(c=="ready")return a(document).ready(e);var h=o(c);h.fn=e,h.sel=g,h.e in l&&(e=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return h.fn.apply(this,arguments)}),h.del=i;var k=i||e;h.proxy=function(a){a=y(a);if(a.isImmediatePropagationStopped())return;a.data=f;var c=k.apply(b,a._args==d?[a]:[a].concat(a._args));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},h.i=n.length,n.push(h),"addEventListener"in b&&b.addEventListener(r(h.e),h.proxy,q(h,j))})}function t(a,b,c,d,e){var f=m(a);(b||"").split(/\s/).forEach(function(b){n(a,b,c,d).forEach(function(b){delete h[f][b.i],"removeEventListener"in a&&a.removeEventListener(r(b.e),b.proxy,q(b,e))})})}function y(b,c){if(c||!b.isDefaultPrevented){c||(c=b),a.each(x,function(a,d){var e=c[a];b[a]=function(){return this[d]=u,e&&e.apply(c,arguments)},b[d]=v});if(c.defaultPrevented!==d?c.defaultPrevented:"returnValue"in c?c.returnValue===!1:c.getPreventDefault&&c.getPreventDefault())b.isDefaultPrevented=u}return b}function z(a){var b,c={originalEvent:a};for(b in a)!w.test(b)&&a[b]!==d&&(c[b]=a[b]);return y(c,a)}var b=a.zepto.qsa,c=1,d,e=Array.prototype.slice,f=a.isFunction,g=function(a){return typeof a=="string"},h={},i={},j="onfocusin"in window,k={focus:"focusin",blur:"focusout"},l={mouseenter:"mouseover",mouseleave:"mouseout"};i.click=i.mousedown=i.mouseup=i.mousemove="MouseEvents",a.event={add:s,remove:t},a.proxy=function(b,c){if(f(b)){var d=function(){return b.apply(c,arguments)};return d._zid=m(b),d}if(g(c))return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b,c){return this.on(a,b,c)},a.fn.unbind=function(a,b){return this.off(a,b)},a.fn.one=function(a,b,c,d){return this.on(a,b,c,d,1)};var u=function(){return!0},v=function(){return!1},w=/^([A-Z]|returnValue$|layer[XY]$)/,x={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(a,b,c){return this.on(b,a,c)},a.fn.undelegate=function(a,b,c){return this.off(b,a,c)},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,h,i,j){var k,l,m=this;if(b&&!g(b))return a.each(b,function(a,b){m.on(a,c,h,b,j)}),m;!g(c)&&!f(i)&&i!==!1&&(i=h,h=c,c=d);if(f(h)||h===!1)i=h,h=d;return i===!1&&(i=v),m.each(function(d,f){j&&(k=function(a){return t(f,a.type,i),i.apply(this,arguments)}),c&&(l=function(b){var d,g=a(b.target).closest(c,f).get(0);if(g&&g!==f)return d=a.extend(z(b),{currentTarget:g,liveFired:f}),(k||i).apply(g,[d].concat(e.call(arguments,1)))}),s(f,b,i,h,c,l||k)})},a.fn.off=function(b,c,e){var h=this;return b&&!g(b)?(a.each(b,function(a,b){h.off(a,c,b)}),h):(!g(c)&&!f(e)&&e!==!1&&(e=c,c=d),e===!1&&(e=v),h.each(function(){t(this,b,e,c)}))},a.fn.trigger=function(b,c){return b=g(b)||a.isPlainObject(b)?a.Event(b):y(b),b._args=c,this.each(function(){"dispatchEvent"in this?this.dispatchEvent(b):a(this).triggerHandler(b,c)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,h){d=z(g(b)?a.Event(b):b),d._args=c,d.target=h,a.each(n(h,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){g(a)||(b=a,a=b.type);var c=document.createEvent(i[a]||"Events"),d=!0;if(b)for(var e in b)e=="bubbles"?d=!!b[e]:c[e]=b[e];return c.initEvent(a,d,!0),y(c)}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.isDefaultPrevented()}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c,d){var e=c.context,f="success";c.success.call(e,a,f,b),d&&d.resolveWith(e,[a,f,b]),triggerGlobal(c,e,"ajaxSuccess",[b,c,a]),ajaxComplete(f,b,c)}function ajaxError(a,b,c,d,e){var f=d.context;d.error.call(f,c,b,a),e&&e.rejectWith(f,[c,b,a]),triggerGlobal(d,f,"ajaxError",[c,d,a||b]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return b==""?a:(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data),a.data=undefined)}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b),g=$.isPlainObject(b);$.each(b,function(b,h){e=$.type(h),d&&(b=c?d:d+"["+(g||e=="object"||e=="array"?b:"")+"]"),!d&&f?a.add(h.name,h.value):e=="array"||!c&&e=="object"?serialize(a,h,c,b):a.add(b,h)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a,b){if("type"in a){var c=a.jsonpCallback,d=($.isFunction(c)?c():c)||"jsonp"+ ++jsonpID,e=document.createElement("script"),f=window[d],g,h=function(a){$(e).triggerHandler("error",a||"abort")},i={abort:h},j;return b&&b.promise(i),$(e).on("load error",function(c,h){clearTimeout(j),$(e).off().remove(),c.type=="error"||!g?ajaxError(null,h||"error",i,a,b):ajaxSuccess(g[0],i,a,b),window[d]=f,g&&$.isFunction(f)&&f(g[0]),f=g=undefined}),ajaxBeforeSend(i,a)===!1?(h("abort"),i):(window[d]=function(){g=arguments},e.src=a.url.replace(/=\?/,"="+d),document.head.appendChild(e),a.timeout>0&&(j=setTimeout(function(){h("timeout")},a.timeout)),i)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{}),deferred=$.Deferred&&$.Deferred();for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,settings.jsonp?settings.jsonp+"=?":settings.jsonp===!1?"":"callback=?")),$.ajaxJSONP(settings,deferred);var mime=settings.accepts[dataType],headers={},setHeader=function(a,b){headers[a.toLowerCase()]=[a,b]},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),nativeSetHeader=xhr.setRequestHeader,abortTimeout;deferred&&deferred.promise(xhr),settings.crossDomain||setHeader("X-Requested-With","XMLHttpRequest"),setHeader("Accept",mime||"*/*");if(mime=settings.mimeType||mime)mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime);(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")&&setHeader("Content-Type",settings.contentType||"application/x-www-form-urlencoded");if(settings.headers)for(name in settings.headers)setHeader(name,settings.headers[name]);xhr.setRequestHeader=setHeader,xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(settings.mimeType||xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings,deferred):ajaxSuccess(result,xhr,settings,deferred)}else ajaxError(xhr.statusText||null,xhr.status?"error":"abort",xhr,settings,deferred)}};if(ajaxBeforeSend(xhr,settings)===!1)return xhr.abort(),ajaxError(null,"abort",xhr,settings,deferred),xhr;if(settings.xhrFields)for(name in settings.xhrFields)xhr[name]=settings.xhrFields[name];var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async,settings.username,settings.password);for(name in headers)nativeSetHeader.apply(xhr,headers[name]);return settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings,deferred)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a([].slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.isDefaultPrevented()||this.get(0).submit()}return this}}(Zepto),function(a){"__proto__"in{}||a.extend(a.zepto,{Z:function(b,c){return b=b||[],a.extend(b,a.fn),b.selector=c||"",b.__Z=!0,b},isZ:function(b){return a.type(b)==="array"&&"__Z"in b}});try{getComputedStyle(undefined)}catch(b){var c=getComputedStyle;window.getComputedStyle=function(a){try{return c(a)}catch(b){return null}}}}(Zepto) \ No newline at end of file diff --git a/js/main.js b/js/main.js index 87cb9e2..b623a9e 100644 --- a/js/main.js +++ b/js/main.js @@ -1,22 +1,17 @@ "use strict"; -yepnope({ - test: window.mobile, - yep : 'js/mobile-events.js', - nope: 'js/events.js' -}) - $(document).ready(function() { window.c = $('canvas')[0].getContext('2d'); window.o = $('canvas')[1].getContext('2d'); window.settings = { - lineWidth : 0.2, - strokeStyle : 'black', + lineWidth : 2, + color : 'black', type: 'sketch', lineCap: 'round', lineJoin: 'round', - furLength: 5 + furLength: 5, + connectTelorance: 40 }; window.points = []; window.$c = $('canvas'); @@ -25,4 +20,17 @@ $(document).ready(function() { 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/mobile-events.js', 'js/libs/color-picker-touch.js'], + nope: ['js/events.js', 'js/libs/color-picker.js'] + }) + }) diff --git a/js/mobile-events.js b/js/mobile-events.js index ca89d0f..2f0fee7 100644 --- a/js/mobile-events.js +++ b/js/mobile-events.js @@ -1,28 +1,63 @@ - $('.menu').bind('touchend', function() { +"use strict"; + +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, $c.width(), $c.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, $c.width(), $c.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 pictures/' + this.result.name); + } + 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.length-1].data, 0, 0); +} + + $('.menu').on('tap', function() { $('#menu').toggleClass('pulled'); }) - $('.save').bind('touchend', function() { - var data = $c[0].toDataURL(); - var img = $(''); - $('body').append(img); - var share = new MozActivity({ - name: 'share', - data: { - type: 'image/*' - } - }) + $('.save').on('tap', function() { + $('#save').removeClass('hidden'); }) - $c.last().bind('touchstart', function(e) { + $c.last().on('touchstart', function(e) { e.preventDefault(); var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY); startPoint(xy.x, xy.y); window.active = true; - }).bind('touchmove', function(e) { + }).on('touchmove', function(e) { e.preventDefault(); if (!window.active || settings.type == 'line') return; var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY); drawPoint(xy.x, xy.y); - }).bind('touchend', function(e) { + }).on('touchend', function(e) { e.preventDefault(); window.active = false; @@ -39,31 +74,67 @@ // Value Selector - var $selector = $('form[data-type="value-selector"]'); + var $single = $('form[data-type="value-selector"].single'); - $selector.find('li').on('touchend', function(e) { - $(this).parent().find('li').removeAttr('aria-selected'); + $single.find('li').on('tap', function(e) { + e.preventDefault(); + $(this).parent().find('li[aria-selected]').removeAttr('aria-selected'); $(this).attr('aria-selected', 'true'); - var prop = $(this).parents('form').attr('id'), - key = $(this).find('label span').html().toLowerCase(); - window.settings[prop] = key; + var key = $(this).parents('form').attr('id'), + value = $(this).find('label span').html().toLowerCase(); + window.settings[key] = value; - $('button[id="set' + prop + '"] span').html(key[0].toUpperCase() + key.substr(1)); + $('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'); }) - $selector.submit(function(e) { + $single.submit(function(e) { e.preventDefault(); $(this).addClass('hidden'); }) + // Confirm + + var $confirm = $('form[data-type="value-selector"].confirm'); + + $confirm.find('li').on('tap', function(e) { + $(this).parent().find('li[aria-selected]').removeAttr('aria-selected'); + $(this).attr('aria-selected', 'true'); + }) + $confirm.find('button').last().on('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 = key.toLowerCase(); + + window[v][key] = value; + } + }) + $(this).parents('form').addClass('hidden'); + window[v](); + }) + $confirm.find('button').first().on('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]; - $(this).on('touchend', function(e) { + if( target == 'color' ) { + return $(this).on('tap', function() { + $('.picker').removeClass('hidden'); + }) + } + $(this).on('tap', function(e) { e.preventDefault(); $('form[id="' + target + '"]').removeClass('hidden'); }) @@ -71,19 +142,49 @@ // Seekbar - var sliderLeft = $('div[role="slider"] button').offset().left; + 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 = e.changedTouches[0].pageX - sliderLeft - 15; - if( x <= 100 && x > 0 ) { + if( $(this).attr('data-moving') ) { + var x = parseInt(e.changedTouches[0].pageX - sliderLeft - 15); + var progress = $(this).parent().children().first(); + var max = +progress.attr('max'); + var min = +progress.attr('min'); + if( x <= max && x >= min ) { $(this).css('left', x+'%'); $(this).parent().find('progress').attr('value', x); - settings.lineWidth = x / 10; - $('#lineWidth span').html(x); + var key = $(this).parents('div[role="slider"]').attr('class'); + settings[key] = x; + $('#'+ key +' span').html(x); } } }).on('touchend', function() { $(this).removeAttr('data-moving'); }) + + // Color Picker + + $('#closePicker').on('tap', function() { + $('.picker').addClass('hidden'); + }) + + // Bottom + + $('#clear').on('tap', function() { + c.clearRect(0, 0, $c.width(), $c.height()); + 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, $c.width(), $c.height()), + points: [] + }) + window.points.history.last = window.points.history.length-1; + }) + + $('#undo').on('tap', undo); + $('#redo').on('tap', redo); + diff --git a/manifest.webapp b/manifest.webapp index 6b2289c..7173527 100644 --- a/manifest.webapp +++ b/manifest.webapp @@ -2,6 +2,8 @@ "name": "Sketchy", "description": "Free Sketch/Paint app", "version": 1, + "fullscreen": true, + "type": "privileged", "launch_path": "/index.html", "icons": { "16": "/img/icons/icon16.png", @@ -22,5 +24,11 @@ "name": "Sketchy", "description": "برنامه‌ی رایگان طراحی/نقاشی" } + }, + "permissions": { + "device-storage:pictures": { + "description": "Required to save sketched pics", + "access": "readwrite" + } } }