diff --git a/.gitignore b/.gitignore
index 4e4a072..0e827d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
nbproject
tmp/*
.DS_Store
+/img.data/
\ No newline at end of file
diff --git a/AportaContenido.php b/AportaContenido.php
index 0b38bcb..ab60c27 100644
--- a/AportaContenido.php
+++ b/AportaContenido.php
@@ -124,14 +124,14 @@ class AportaContenido {
public function __call($metodo, $parametros) {
switch ($metodo) { // Dependiendo del método invocado
case 'titulo': // devolvemos el título
- return PROGRAMA.VERSION;
+ return PROGRAMA." v".VERSION;
case 'usuario':
if ($this->registrado)
return "Usuario=$this->usuario";
else
return '';
case 'fecha': return $this->fechaActual();
- case 'aplicacion': return PROGRAMA.VERSION;
+ case 'aplicacion': return PROGRAMA." v".VERSION;
case 'menu': // el menú
if ($this->registrado) {
return $this->miMenu->insertaMenu();
@@ -187,7 +187,7 @@ class AportaContenido {
case 'ubicaciones':
case 'test':
case 'elementos':
- $this->cargaDatosURL();
+ $this->DatosURL();
if ($this->datosURL['opc'] == "informe") {
if (!$this->pefil['Informe']) {
$this->procesaURL();
@@ -284,31 +284,19 @@ class AportaContenido {
}
case 'copiaseg':
if ($this->perfil['Config']) {
- $archivo_sql = "tmp/copiaseg.sql";
- $archivo = $archivo_sql . ".gz";
- if (file_exists($archivo)) {
- unlink($archivo);
- }
- $comando = escapeshellcmd(MYSQLDUMP . ' -h ' . SERVIDOR . ' -P ' . PUERTO . ' -u ' . USUARIO . ' --password=' . CLAVE . ' --result-file=' . $archivo_sql . ' ' . BASEDATOS);
- $comando2 = escapeshellcmd(GZIP . ' -9f ' . $archivo_sql);
- exec($comando);
- exec($comando2);
- if (filesize($archivo) < 1024) {
- //No se ha realizado la copia de seguridad
- $mensaje = "La copia de seguridad no se ha realizado correctamente.
";
- $mensaje .= "Compruebe que las rutas a los programas mysqldump y gzip en configuración están correctamente establecidas ";
- $mensaje .= "y que los datos de acceso a la base de datos sean correctos.
";
- $mensaje .= "mysqldump=[" . MYSQLDUMP . "]
";
- $mensaje .= "gzip=[" . GZIP . "]";
- $cabecera = "ERROR";
- $tipo = "danger";
+ $copia = new CopiaSeguridad();
+ if ($_GET['confirmado'] == "1") {
+ if (!$copia->creaCopia()) {
+ $tipo = "danger";
+ $cabecera = "ERROR";
+ } else {
+ $tipo = "info";
+ $cabecera = "INFORMACIÓN";
+ }
+ return $this->panel($cabecera, $copia->mensaje(), $tipo);
} else {
- $mensaje .= 'Copia de seguridad realizada con éxito.
Pulse sobre el siguiente enlace para descargar:
';
- $mensaje .= 'Descargar Copia de Seguridad de Datos
';
- $cabecera = "Información";
- $tipo = "success";
+ return $copia->dialogo();
}
- return $this->panel($cabecera,$mensaje,$tipo);
} else {
return $this->mensajePermisos("Copias de seguridad");
}
diff --git a/CopiaSeguridad.php b/CopiaSeguridad.php
new file mode 100644
index 0000000..db5941f
--- /dev/null
+++ b/CopiaSeguridad.php
@@ -0,0 +1,131 @@
+.
+ *
+ */
+class CopiaSeguridad {
+ private $mensaje;
+ private $baseDatos;
+ private $imagenes;
+
+ public function __construct()
+ {
+ $opcion = $_GET['opc'];
+ }
+ public function creaCopia()
+ {
+ if (!$this->copiaBaseDatos()) {
+ return false;
+ }
+ if (!$this->copiaImagenes()) {
+ return false;
+ }
+ if (!$this->empaqueta()) {
+ return false;
+ }
+ return true;
+ }
+ public function dialogo()
+ {
+ $dialogo = '
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // apply the "grayscale" filter
+ * $img->apply_filter('grayscale');
+ *
+ * // apply the "contrast" filter
+ * $img->apply_filter('contrast', -20);
+ *
+ *
+ * You can also apply multiple filters at once. In this case, the method requires a single argument, an array of
+ * arrays, containing the filters and associated arguments, where applicable:
+ *
+ *
+ * // create a sepia effect
+ * // note how we're applying multiple filters at once
+ * // each filter is in its own array
+ * $img->apply_filter(array(
+ *
+ * // first we apply the "grayscale" filter
+ * array('grayscale'),
+ *
+ * // then we apply the "colorize" filter with 90, 60, 40 as
+ * // the values for red, green and blue
+ * array('colorize', 90, 60, 40),
+ *
+ * ));
+ *
+ *
+ * @param string $filter The (case-insensitive) name of the filter to apply. Can be one of the following:
+ *
+ * - brightness - changes the brightness of the image; use arg1
+ * to set the level of brightness; the range of brightness
+ * is -255 to 255;
+ * - colorize - adds (subtracts) specified RGB values to each pixel;
+ * use arg1, arg2 and arg3 in the
+ * form of red, green, blue and arg4 for the alpha
+ * channel. the range for each color is -255 to 255 and
+ * 0 to 127 for alpha; alpha support is available only
+ * for PHP 5.2.5+;
+ * - contrast - changes the contrast of the image; use arg1
+ * to set the level of contrast; the range of contrast
+ * is -100 to 100;
+ * - gausian_blur - blurs the image using the Gaussian method;
+ * - grayscale - converts the image into grayscale;
+ * - edgedetect - uses edge detection to highlight the edges in the image;
+ * - emboss - embosses the image;
+ * - mean_removal - uses mean removal to achieve a "sketchy" effect;
+ * - negate - reverses all the colors of the image;
+ * - pixelate - applies pixelation effect to the image, use arg1
+ * to set the block size and arg2 to set the
+ * pixelation effect mode; this filter is available
+ * only for PHP 5.3.0+;
+ * - selective_blur - blurs the image;
+ * - smooth - makes the image smoother. Use arg1 to set the
+ * level of smoothness. applies a 9-cell convolution matrix
+ * where center pixel has the weight of arg1 and
+ * others weight of 1.0. the result is normalized by dividing
+ * the sum with arg1 + 8.0 (sum of the matrix).
+ * any float is accepted;
+ *
+ * @param mixed $arg1 Used by the following filters:
+ * - brightness - sets the brightness level (-255 to 255)
+ * - contrast - sets the contrast level (-100 to 100)
+ * - colorize - sets the value of the red component (-255 to 255)
+ * - smooth - sets the smoothness level
+ * - pixelate - sets the block size, in pixels
+ *
+ * @param mixed $arg2 Used by the following filters:
+ * - colorize - sets the value of the green component (-255 to 255)
+ * - pixelate - whether to use advanced pixelation effect or not (defaults to FALSE).
+ *
+ * @param mixed $arg3 Used by the following filters:
+ * - colorize - sets the value of the blue component (-255 to 255)
+ *
+ * @param mixed $arg4 Used by the following filters:
+ * - colorize - alpha channel; a value between 0 and 127. 0 indicates
+ * completely opaque while 127 indicates completely
+ * transparent.
+ *
+ * @since 2.2.2
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If {@link http://php.net/manual/en/function.imagefilter.php imagefilter} is not
+ * available the method will return FALSE without setting an {@link error} code.
+ *
+ * If the requested filter doesn't exist, or invalid arguments are passed, the method
+ * will trigger a warning.
+ *
+ * If FALSE is returned and you are sure that
+ * {@link http://php.net/manual/en/function.imagefilter.php imagefilter} exists and that
+ * the requested filter is valid, check the {@link error} property to see the error code.
+ */
+ function apply_filter($filter, $arg1 = '', $arg2 = '', $arg3 = '', $arg4 = '')
+ {
+
+ // if "imagefilter" function exists and the requested filter exists
+ if (function_exists('imagefilter'))
+
+ // if image resource was successfully created
+ if ($this->_create_from_source()) {
+
+ // prepare the target image
+ $target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1);
+
+ // copy the original image
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ 0,
+ 0,
+ $this->source_width,
+ $this->source_height,
+ $this->source_width,
+ $this->source_height
+
+ );
+
+ // if multiple filters are to be applied at once
+ if (is_array($filter)) {
+
+ // iterate through the filters
+ foreach ($filter as $arguments)
+
+ // if filter exists
+ if (defined('IMG_FILTER_' . strtoupper($arguments[0]))) {
+
+ // try to apply the filter...
+ if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($arguments[0]))), array_slice($arguments, 1))))
+
+ // ...and trigger an error if the filter could not be applied
+ trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING);
+
+ // if filter doesn't exists, trigger an error
+ } else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING);
+
+ // if a single filter is to be applied and it is available
+ } elseif (defined('IMG_FILTER_' . strtoupper($filter))) {
+
+ // get all the arguments passed to the method
+ $arguments = func_get_args();
+
+ // try to apply the filter...
+ if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($filter))), array_slice($arguments, 1))))
+
+ // ...and trigger an error if the filter could not be applied
+ trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING);
+
+ // if filter doesn't exists, trigger an error
+ } else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING);
+
+ // write image
+ return $this->_write_image($target_identifier);
+
+ }
+
+ // if script gets this far, return false
+ // note that we do not set the error level as it has been already set
+ // by the _create_from_source() method earlier, if the case
+ return false;
+
+ }
+
+ /**
+ * Crops a portion of the image given as {@link source_path} and outputs it as the file specified as {@link target_path}.
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // crop a rectangle of 100x100 pixels, starting from the top-left corner
+ * $img->crop(0, 0, 100, 100);
+ *
+ *
+ * @param integer $start_x x coordinate to start cropping from
+ *
+ * @param integer $start_y y coordinate to start cropping from
+ *
+ * @param integer $end_x x coordinate where to end the cropping
+ *
+ * @param integer $end_y y coordinate where to end the cropping
+ *
+ * @since 1.0.4
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ */
+ function crop($start_x, $start_y, $end_x, $end_y)
+ {
+
+ // this method might be also called internally
+ // in this case, there's a fifth argument that points to an already existing image identifier
+ $args = func_get_args();
+
+ // if fifth argument exists
+ if (isset($args[4]) && is_resource($args[4])) {
+
+ // that it is the image identifier that we'll be using further on
+ $this->source_identifier = $args[4];
+
+ // set this to true so that the script will continue to execute at the next IF
+ $result = true;
+
+ // if method is called as usually
+ // try to create an image resource from source path
+ } else $result = $this->_create_from_source();
+
+ // if image resource was successfully created
+ if ($result !== false) {
+
+ // prepare the target image
+ $target_identifier = $this->_prepare_image($end_x - $start_x, $end_y - $start_y, -1);
+
+ // crop the image
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ $start_x,
+ $start_y,
+ $end_x - $start_x,
+ $end_y - $start_y,
+ $end_x - $start_x,
+ $end_y - $start_y
+
+ );
+
+ // write image
+ return $this->_write_image($target_identifier);
+
+ }
+
+ // if script gets this far, return false
+ // note that we do not set the error level as it has been already set
+ // by the _create_from_source() method earlier
+ return false;
+
+ }
+
+ /**
+ * Flips both horizontally and vertically the image given as {@link source_path} and outputs the resulted image as
+ * {@link target_path}
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // flip the image both horizontally and vertically
+ * $img->flip_both();
+ *
+ *
+ * @since 2.1
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ */
+ function flip_both()
+ {
+
+ return $this->_flip('both');
+
+ }
+
+ /**
+ * Flips horizontally the image given as {@link source_path} and outputs the resulted image as {@link target_path}
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // flip the image horizontally
+ * $img->flip_horizontal();
+ *
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ */
+ function flip_horizontal()
+ {
+
+ return $this->_flip('horizontal');
+
+ }
+
+ /**
+ * Flips vertically the image given as {@link source_path} and outputs the resulted image as {@link target_path}
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // flip the image vertically
+ * $img->flip_vertical();
+ *
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ */
+ function flip_vertical()
+ {
+
+ return $this->_flip('vertical');
+
+ }
+
+ /**
+ * Resizes the image given as {@link source_path} and outputs the resulted image as {@link target_path}.
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // apply a "sharpen" filter to the resulting images
+ * $img->sharpen_images = true;
+ *
+ * // resize the image to exactly 150x150 pixels, without altering aspect ratio, by using the CROP_CENTER method
+ * $img->resize(150, 150, ZEBRA_IMAGE_CROP_CENTER);
+ *
+ *
+ * @param integer $width The width to resize the image to.
+ *
+ * If set to 0, the width will be automatically adjusted, depending
+ * on the value of the height argument so that the image preserves
+ * its aspect ratio.
+ *
+ * If {@link preserve_aspect_ratio} is set to TRUE and both this and the
+ * height arguments are values greater than 0, the image will
+ * be resized to the exact required width and height and the aspect ratio
+ * will be preserved - (also see the description for the method
+ * argument below on how can this be done).
+ *
+ * If {@link preserve_aspect_ratio} is set to FALSE, the image will be
+ * resized to the required width and the aspect ratio will be ignored.
+ *
+ * If both width and height are set to 0, a copy of
+ * the source image will be created ({@link jpeg_quality} and
+ * {@link png_compression} will still apply).
+ *
+ * If either width or height are set to 0, the script
+ * will consider the value of the {@link preserve_aspect_ratio} to bet set
+ * to TRUE regardless of its actual value!
+ *
+ * @param integer $height The height to resize the image to.
+ *
+ * If set to 0, the height will be automatically adjusted, depending
+ * on the value of the width argument so that the image preserves
+ * its aspect ratio.
+ *
+ * If {@link preserve_aspect_ratio} is set to TRUE and both this and the
+ * width arguments are values greater than 0, the image will
+ * be resized to the exact required width and height and the aspect ratio
+ * will be preserved - (also see the description for the method
+ * argument below on how can this be done).
+ *
+ * If {@link preserve_aspect_ratio} is set to FALSE, the image will be
+ * resized to the required height and the aspect ratio will be ignored.
+ *
+ * If both width and height are set to 0, a copy of
+ * the source image will be created ({@link jpeg_quality} and
+ * {@link png_compression} will still apply).
+ *
+ * If either height or width are set to 0, the script
+ * will consider the value of the {@link preserve_aspect_ratio} to bet set
+ * to TRUE regardless of its actual value!
+ *
+ * @param int $method (Optional) Method to use when resizing images to exact width and height
+ * while preserving aspect ratio.
+ *
+ * If the {@link preserve_aspect_ratio} property is set to TRUE and both the
+ * width and height arguments are values greater than 0,
+ * the image will be resized to the exact given width and height and the
+ * aspect ratio will be preserved by using on of the following methods:
+ *
+ * - ZEBRA_IMAGE_BOXED - the image will be scalled so that it will
+ * fit in a box with the given width and height (both width/height will
+ * be smaller or equal to the required width/height) and then it will
+ * be centered both horizontally and vertically. The blank area will be
+ * filled with the color specified by the bgcolor argument. (the
+ * blank area will be filled only if the image is not transparent!)
+ *
+ * - ZEBRA_IMAGE_NOT_BOXED - the image will be scalled so that it
+ * could fit in a box with the given width and height but will
+ * not be enclosed in a box with given width and height. The new width/
+ * height will be both smaller or equal to the required width/height
+ *
+ * - ZEBRA_IMAGE_CROP_TOPLEFT
+ * - ZEBRA_IMAGE_CROP_TOPCENTER
+ * - ZEBRA_IMAGE_CROP_TOPRIGHT
+ * - ZEBRA_IMAGE_CROP_MIDDLELEFT
+ * - ZEBRA_IMAGE_CROP_CENTER
+ * - ZEBRA_IMAGE_CROP_MIDDLERIGHT
+ * - ZEBRA_IMAGE_CROP_BOTTOMLEFT
+ * - ZEBRA_IMAGE_CROP_BOTTOMCENTER
+ * - ZEBRA_IMAGE_CROP_BOTTOMRIGHT
+ *
+ * For the methods involving crop, first the image is scaled so that both
+ * its sides are equal or greater than the respective sizes of the bounding
+ * box; next, a region of required width and height will be cropped from
+ * indicated region of the resulted image.
+ *
+ * Default is ZEBRA_IMAGE_CROP_CENTER
+ *
+ * @param hexadecimal $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the
+ * blank area. See the method argument.
+ *
+ * When set to -1 the script will preserve transparency for transparent GIF
+ * and PNG images. For non-transparent images the background will be white
+ * in this case.
+ *
+ * Default is #FFFFFF.
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see what went
+ * wrong
+ */
+ function resize($width = 0, $height = 0, $method = ZEBRA_IMAGE_CROP_CENTER, $background_color = '#FFFFFF')
+ {
+
+ // if image resource was successfully created
+ if ($this->_create_from_source()) {
+
+ // if either width or height is to be adjusted automatically
+ // set a flag telling the script that, even if $preserve_aspect_ratio is set to false
+ // treat everything as if it was set to true
+ if ($width == 0 || $height == 0) $auto_preserve_aspect_ratio = true;
+
+ // if aspect ratio needs to be preserved
+ if ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) {
+
+ // if height is given and width is to be computed accordingly
+ if ($width == 0 && $height > 0) {
+
+ // get the original image's aspect ratio
+ $aspect_ratio = $this->source_width / $this->source_height;
+
+ // the target image's height is as given as argument to the method
+ $target_height = $height;
+
+ // compute the target image's width, preserving the aspect ratio
+ $target_width = round($height * $aspect_ratio);
+
+ // if width is given and height is to be computed accordingly
+ } elseif ($width > 0 && $height == 0) {
+
+ // get the original image's aspect ratio
+ $aspect_ratio = $this->source_height / $this->source_width;
+
+ // the target image's width is as given as argument to the method
+ $target_width = $width;
+
+ // compute the target image's height, preserving the aspect ratio
+ $target_height = round($width * $aspect_ratio);
+
+ // if both width and height are given and ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED methods are to be used
+ } elseif ($width > 0 && $height > 0 && ($method == 0 || $method == 1)) {
+
+ // compute the horizontal and vertical aspect ratios
+ $vertical_aspect_ratio = $height / $this->source_height;
+ $horizontal_aspect_ratio = $width / $this->source_width;
+
+ // if the image's newly computed height would be inside the bounding box
+ if (round($horizontal_aspect_ratio * $this->source_height < $height)) {
+
+ // the target image's width is as given as argument to the method
+ $target_width = $width;
+
+ // compute the target image's height so that the image will stay inside the bounding box
+ $target_height = round($horizontal_aspect_ratio * $this->source_height);
+
+ // otherwise
+ } else {
+
+ // the target image's height is as given as argument to the method
+ $target_height = $height;
+
+ // compute the target image's width so that the image will stay inside the bounding box
+ $target_width = round($vertical_aspect_ratio * $this->source_width);
+
+ }
+
+ // if both width and height are given and image is to be cropped in order to get to the required size
+ } elseif ($width > 0 && $height > 0 && $method > 1 && $method < 11) {
+
+ // compute the horizontal and vertical aspect ratios
+ $vertical_aspect_ratio = $this->source_height / $height;
+ $horizontal_aspect_ratio = $this->source_width / $width;
+
+ // we'll use one of the two
+ $aspect_ratio =
+
+ $vertical_aspect_ratio < $horizontal_aspect_ratio ?
+
+ $vertical_aspect_ratio :
+
+ $horizontal_aspect_ratio;
+
+ // compute the target image's width, preserving the aspect ratio
+ $target_width = round($this->source_width / $aspect_ratio);
+
+ // compute the target image's height, preserving the aspect ratio
+ $target_height = round($this->source_height / $aspect_ratio);
+
+ // for any other case
+ } else {
+
+ // we will create a copy of the source image
+ $target_width = $this->source_width;
+ $target_height = $this->source_height;
+
+ }
+
+ // if aspect ratio does not need to be preserved
+ } else {
+
+ // compute the target image's width
+ $target_width = ($width > 0 ? $width : $this->source_width);
+
+ // compute the target image's height
+ $target_height = ($height > 0 ? $height : $this->source_height);
+
+ }
+
+ // if
+ if (
+
+ // all images are to be resized - including images that are smaller than the given width/height
+ $this->enlarge_smaller_images ||
+
+ // smaller images than the given width/height are to be left untouched
+ // but current image has at leas one side that is larger than the required width/height
+ ($width > 0 && $height > 0 ?
+
+ ($this->source_width > $width || $this->source_height > $height) :
+
+ ($this->source_width > $target_width || $this->source_height > $target_height)
+
+ )
+
+ ) {
+
+ // if
+ if (
+
+ // aspect ratio needs to be preserved AND
+ ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) &&
+
+ // both width and height are given
+ ($width > 0 && $height > 0) &&
+
+ // images are to be cropped
+ ($method > 1 && $method < 11)
+
+ ) {
+
+ // prepare the target image
+ $target_identifier = $this->_prepare_image($target_width, $target_height, $background_color);
+
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ 0,
+ 0,
+ $target_width,
+ $target_height,
+ $this->source_width,
+ $this->source_height
+
+ );
+
+ // do the crop according to the required method
+ switch ($method) {
+
+ // if image needs to be cropped from the top-left corner
+ case ZEBRA_IMAGE_CROP_TOPLEFT:
+
+ // crop accordingly
+ return $this->crop(
+ 0,
+ 0,
+ $width,
+ $height,
+ $target_identifier // crop this resource instead
+ );
+
+ break;
+
+ // if image needs to be cropped from the top-center
+ case ZEBRA_IMAGE_CROP_TOPCENTER:
+
+ // crop accordingly
+ return $this->crop(
+ floor(($target_width - $width) / 2),
+ 0,
+ floor(($target_width - $width) / 2) + $width,
+ $height,
+ $target_identifier // crop this resource instead
+ );
+
+ break;
+
+ // if image needs to be cropped from the top-right corner
+ case ZEBRA_IMAGE_CROP_TOPRIGHT:
+
+ // crop accordingly
+ return $this->crop(
+ $target_width - $width,
+ 0,
+ $target_width,
+ $height,
+ $target_identifier // crop this resource instead
+ );
+
+ break;
+
+ // if image needs to be cropped from the middle-left
+ case ZEBRA_IMAGE_CROP_MIDDLELEFT:
+
+ // crop accordingly
+ return $this->crop(
+
+ 0,
+ floor(($target_height - $height) / 2),
+ $width,
+ floor(($target_height - $height) / 2) + $height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ // if image needs to be cropped from the center of the image
+ case ZEBRA_IMAGE_CROP_CENTER:
+
+ // crop accordingly
+ return $this->crop(
+
+ floor(($target_width - $width) / 2),
+ floor(($target_height - $height) / 2),
+ floor(($target_width - $width) / 2) + $width,
+ floor(($target_height - $height) / 2) + $height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ // if image needs to be cropped from the middle-right
+ case ZEBRA_IMAGE_CROP_MIDDLERIGHT:
+
+ // crop accordingly
+ return $this->crop(
+
+ $target_width - $width,
+ floor(($target_height - $height) / 2),
+ $target_width,
+ floor(($target_height - $height) / 2) + $height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ // if image needs to be cropped from the bottom-left corner
+ case ZEBRA_IMAGE_CROP_BOTTOMLEFT:
+
+ // crop accordingly
+ return $this->crop(
+
+ 0,
+ $target_height - $height,
+ $width,
+ $target_height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ // if image needs to be cropped from the bottom-center
+ case ZEBRA_IMAGE_CROP_BOTTOMCENTER:
+
+ // crop accordingly
+ return $this->crop(
+
+ floor(($target_width - $width) / 2),
+ $target_height - $height,
+ floor(($target_width - $width) / 2) + $width,
+ $target_height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ // if image needs to be cropped from the bottom-right corner
+ case ZEBRA_IMAGE_CROP_BOTTOMRIGHT:
+
+ // crop accordingly
+ return $this->crop(
+
+ $target_width - $width,
+ $target_height - $height,
+ $target_width,
+ $target_height,
+ $target_identifier // crop this resource instead
+
+ );
+
+ break;
+
+ }
+
+ // if aspect ratio doesn't need to be preserved or
+ // it needs to be preserved and method is ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED
+ } else {
+
+ // prepare the target image
+ $target_identifier = $this->_prepare_image(
+ ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $width : $target_width),
+ ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $height : $target_height),
+ $background_color
+ );
+
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($width - $target_width) / 2 : 0),
+ ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($height - $target_height) / 2 : 0),
+ 0,
+ 0,
+ $target_width,
+ $target_height,
+ $this->source_width,
+ $this->source_height
+
+ );
+
+ // if script gets this far, write the image to disk
+ return $this->_write_image($target_identifier);
+
+ }
+
+ // if we get here it means that
+ // smaller images than the given width/height are to be left untouched
+ // therefore, we save the image as it is
+ } else return $this->_write_image($this->source_identifier);
+
+ }
+
+ // if script gets this far return false
+ // note that we do not set the error level as it has been already set
+ // by the _create_from_source() method earlier
+ return false;
+
+ }
+
+ /**
+ * Rotates the image given as {@link source_path} and outputs the resulted image as {@link target_path}.
+ *
+ *
+ * // include the Zebra_Image library
+ * require 'path/to/Zebra_Image.php';
+ *
+ * // instantiate the class
+ * $img = new Zebra_Image();
+ *
+ * // a source image
+ * $img->source_path = 'path/to/source.ext';
+ *
+ * // path to where should the resulting image be saved
+ * // note that by simply setting a different extension to the file will
+ * // instruct the script to create an image of that particular type
+ * $img->target_path = 'path/to/target.ext';
+ *
+ * // rotate the image 45 degrees, clockwise
+ * $img->rotate(45);
+ *
+ *
+ * @param double $angle Angle by which to rotate the image clockwise.
+ *
+ * Between 0 and 360.
+ *
+ * @param mixed $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the
+ * uncovered zone after the rotation.
+ *
+ * When set to -1 the script will preserve transparency for transparent GIF
+ * and PNG images. For non-transparent images the background will be white
+ * in this case.
+ *
+ * Default is -1.
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error
+ * code.
+ */
+ function rotate($angle, $background_color = -1)
+ {
+
+ // if image resource was successfully created
+ if ($this->_create_from_source()) {
+
+ // angles are given clockwise but imagerotate works counterclockwise so we need to negate our value
+ $angle = -$angle;
+
+ // if source image is PNG
+ if ($this->source_type == IMAGETYPE_PNG && $background_color == -1) {
+
+ // rotate the image
+ // but if using -1 as background color didn't work (as is the case for PNG8)
+ if (!($target_identifier = imagerotate($this->source_identifier, $angle, -1))) {
+
+ // we will be using #FFF as the color to fill the uncovered zone after the rotation
+ $background_color = imagecolorallocate($this->source_identifier, 255, 255, 255);
+
+ // rotate the image
+ $target_identifier = imagerotate($this->source_identifier, $angle, $background_color);
+
+ }
+
+ // if source image is a transparent GIF
+ } elseif ($this->source_type == IMAGETYPE_GIF && $this->source_transparent_color_index >= 0) {
+
+ // convert the background color to RGB values
+ $background_color = $this->_hex2rgb($background_color);
+
+ // allocate the color to the image identifier
+ $background_color = imagecolorallocate(
+
+ $this->source_identifier,
+ $background_color['r'],
+ $background_color['g'],
+ $background_color['b']
+
+ );
+
+ // rotate the image
+ $this->source_identifier = imagerotate($this->source_identifier, $angle, $background_color);
+
+ // get the width of rotated image
+ $width = imagesx($this->source_identifier);
+
+ // get the height of rotated image
+ $height = imagesy($this->source_identifier);
+
+ // create a blank image with the new width and height
+ // (this intermediary step is for preserving transparency)
+ $target_identifier = $this->_prepare_image($width, $height, -1);
+
+ // copy the rotated image on to the new one
+ imagecopyresampled($target_identifier, $this->source_identifier, 0, 0, 0, 0, $width, $height, $width, $height);
+
+ // for the other cases
+ } else {
+
+ // convert the color to RGB values
+ $background_color = $this->_hex2rgb($background_color);
+
+ // allocate the color to the image identifier
+ $background_color = imagecolorallocate(
+
+ $this->source_identifier,
+ $background_color['r'],
+ $background_color['g'],
+ $background_color['b']
+
+ );
+
+ // rotate the image
+ $target_identifier = imagerotate($this->source_identifier, $angle, $background_color);
+
+ }
+
+ // write image
+ $this->_write_image($target_identifier);
+
+ }
+
+ // if script gets this far return false
+ // note that we do not set the error level as it has been already set
+ // by the _create_from_source() method earlier
+ return false;
+
+ }
+
+ /**
+ * Returns an array containing the image identifier representing the image obtained from {@link $source_path}, the
+ * image's width and height and the image's type
+ *
+ * @access private
+ */
+ function _create_from_source()
+ {
+
+ // perform some error checking first
+ // if the GD library is not installed
+ if (!function_exists('gd_info')) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 7;
+
+ return false;
+
+ // if source file does not exist
+ } elseif (!is_file($this->source_path)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 1;
+
+ return false;
+
+ // if source file is not readable
+ } elseif (!is_readable($this->source_path)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 2;
+
+ return false;
+
+ // if target file is same as source file and source file is not writable
+ } elseif ($this->target_path == $this->source_path && !is_writable($this->source_path)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 3;
+
+ return false;
+
+ // try to get source file width, height and type
+ // and if it founds an unsupported file type
+ } elseif (!list($this->source_width, $this->source_height, $this->source_type) = @getimagesize($this->source_path)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 4;
+
+ return false;
+
+ // if no errors so far
+ } else {
+
+ // get target file's type based on the file extension
+ $this->target_type = strtolower(substr($this->target_path, strrpos($this->target_path, '.') + 1));
+
+ // create an image from file using extension dependant function
+ // checks for file extension
+ switch ($this->source_type) {
+
+ // if GIF
+ case IMAGETYPE_GIF:
+
+ // create an image from file
+ $identifier = imagecreatefromgif($this->source_path);
+
+ // get the index of the transparent color (if any)
+ if (($this->source_transparent_color_index = imagecolortransparent($identifier)) >= 0)
+
+ // get the transparent color's RGB values
+ // we have to mute errors because there are GIF images which *are* transparent and everything
+ // works as expected, but imagecolortransparent() returns a color that is outside the range of
+ // colors in the image's pallette...
+ $this->source_transparent_color = @imagecolorsforindex($identifier, $this->source_transparent_color_index);
+
+ break;
+
+ // if JPEG
+ case IMAGETYPE_JPEG:
+
+ // create an image from file
+ $identifier = imagecreatefromjpeg($this->source_path);
+
+ break;
+
+ // if PNG
+ case IMAGETYPE_PNG:
+
+ // create an image from file
+ $identifier = imagecreatefrompng($this->source_path);
+
+ // disable blending
+ imagealphablending($identifier, false);
+
+ break;
+
+ default:
+
+ // if unsupported file type
+ // note that we call this if the file is not GIF, JPG or PNG even though the getimagesize function
+ // handles more image types
+ $this->error = 4;
+
+ return false;
+
+ }
+
+ }
+
+ // if target file has to have the same timestamp as the source image
+ // save it as a global property of the class
+ if ($this->preserve_time) $this->source_image_time = filemtime($this->source_path);
+
+ // make available the source image's identifier
+ $this->source_identifier = $identifier;
+
+ return true;
+
+ }
+
+ /**
+ * Converts a hexadecimal representation of a color (i.e. #123456 or #AAA) to a RGB representation.
+ *
+ * The RGB values will be a value between 0 and 255 each.
+ *
+ * @param string $color Hexadecimal representation of a color (i.e. #123456 or #AAA).
+ *
+ * @param string $default_on_error Hexadecimal representation of a color to be used in case $color is not
+ * recognized as a hexadecimal color.
+ *
+ * @return array Returns an associative array with the values of (R)ed, (G)reen and (B)lue
+ *
+ * @access private
+ */
+ function _hex2rgb($color, $default_on_error = '#FFFFFF')
+ {
+
+ // if color is not formatted correctly
+ // use the default color
+ if (preg_match('/^#?([a-f]|[0-9]){3}(([a-f]|[0-9]){3})?$/i', $color) == 0) $color = $default_on_error;
+
+ // trim off the "#" prefix from $background_color
+ $color = ltrim($color, '#');
+
+ // if color is given using the shorthand (i.e. "FFF" instead of "FFFFFF")
+ if (strlen($color) == 3) {
+
+ $tmp = '';
+
+ // take each value
+ // and duplicate it
+ for ($i = 0; $i < 3; $i++) $tmp .= str_repeat($color[$i], 2);
+
+ // the color in it's full, 6 characters length notation
+ $color = $tmp;
+
+ }
+
+ // decimal representation of the color
+ $int = hexdec($color);
+
+ // extract and return the RGB values
+ return array(
+
+ 'r' => 0xFF & ($int >> 0x10),
+ 'g' => 0xFF & ($int >> 0x8),
+ 'b' => 0xFF & $int
+
+ );
+
+ }
+
+ /**
+ * Flips horizontally or vertically or both ways the image given as {@link source_path}.
+ *
+ * @since 2.1
+ *
+ * @access private
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ */
+ function _flip($orientation)
+ {
+
+ // if image resource was successfully created
+ if ($this->_create_from_source()) {
+
+ // prepare the target image
+ $target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1);
+
+ // flip according to $orientation
+ switch ($orientation) {
+
+ case 'horizontal':
+
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ ($this->source_width - 1),
+ 0,
+ $this->source_width,
+ $this->source_height,
+ -$this->source_width,
+ $this->source_height
+
+ );
+
+ break;
+
+ case 'vertical':
+
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ 0,
+ ($this->source_height - 1),
+ $this->source_width,
+ $this->source_height,
+ $this->source_width,
+ -$this->source_height
+
+ );
+
+ break;
+
+ case 'both':
+
+ imagecopyresampled(
+
+ $target_identifier,
+ $this->source_identifier,
+ 0,
+ 0,
+ ($this->source_width - 1),
+ ($this->source_height - 1),
+ $this->source_width,
+ $this->source_height,
+ -$this->source_width,
+ -$this->source_height
+
+ );
+
+ break;
+
+ }
+
+ // write image
+ return $this->_write_image($target_identifier);
+
+ }
+
+ // if script gets this far, return false
+ // note that we do not set the error level as it has been already set
+ // by the _create_from_source() method earlier
+ return false;
+
+ }
+
+ /**
+ * Creates a blank image of given width, height and background color.
+ *
+ * @param integer $width Width of the new image.
+ *
+ * @param integer $height Height of the new image.
+ *
+ * @param string $background_color (Optional) The hexadecimal color of the background.
+ *
+ * Can also be -1 case in which the script will try to create a transparent
+ * image, if possible.
+ *
+ * Default is "#FFFFFF".
+ *
+ * @return Returns the identifier of the newly created image.
+ *
+ * @access private
+ */
+ function _prepare_image($width, $height, $background_color = '#FFFFFF')
+ {
+
+ // create a blank image
+ $identifier = imagecreatetruecolor((int)$width <= 0 ? 1 : (int)$width, (int)$height <= 0 ? 1 : (int)$height);
+
+ // if we are creating a PNG image
+ if ($this->target_type == 'png' && $background_color == -1) {
+
+ // disable blending
+ imagealphablending($identifier, false);
+
+ // allocate a transparent color
+ $transparent_color = imagecolorallocatealpha($identifier, 0, 0, 0, 127);
+
+ // fill the image with the transparent color
+ imagefill($identifier, 0, 0, $transparent_color);
+
+ //save full alpha channel information
+ imagesavealpha($identifier, true);
+
+ // if source image is a transparent GIF
+ } elseif ($this->target_type == 'gif' && $background_color == -1 && $this->source_transparent_color_index >= 0) {
+
+ // allocate the source image's transparent color also to the new image resource
+ $transparent_color = imagecolorallocate(
+ $identifier,
+ $this->source_transparent_color['red'],
+ $this->source_transparent_color['green'],
+ $this->source_transparent_color['blue']
+ );
+
+ // fill the background of the new image with transparent color
+ imagefill($identifier, 0, 0, $transparent_color);
+
+ // from now on, every pixel having the same RGB as the transparent color will be transparent
+ imagecolortransparent($identifier, $transparent_color);
+
+ // for other image types
+ } else {
+
+ // if transparent background color specified, revert to white
+ if ($background_color == -1) $background_color = '#FFFFFF';
+
+ // convert hex color to rgb
+ $background_color = $this->_hex2rgb($background_color);
+
+ // prepare the background color
+ $background_color = imagecolorallocate($identifier, $background_color['r'], $background_color['g'], $background_color['b']);
+
+ // fill the image with the background color
+ imagefill($identifier, 0, 0, $background_color);
+
+ }
+
+ // return the image's identifier
+ return $identifier;
+
+ }
+
+ /**
+ * Sharpens images. Useful when creating thumbnails.
+ *
+ * Code taken from the comments at {@link http://docs.php.net/imageconvolution}.
+ *
+ * This function will yield a result only for PHP version 5.1.0+ and will leave the image unaltered for older
+ * versions!
+ *
+ * @param $identifier identifier An image identifier
+ *
+ * @access private
+ */
+ function _sharpen_image($image)
+ {
+
+ // if the "sharpen_images" is set to true and we're running an appropriate version of PHP
+ // (the "imageconvolution" is available only for PHP 5.1.0+)
+ if ($this->sharpen_images && version_compare(PHP_VERSION, '5.1.0') >= 0) {
+
+ // the convolution matrix as an array of three arrays of three floats
+ $matrix = array(
+ array(-1.2, -1, -1.2),
+ array(-1, 20, -1),
+ array(-1.2, -1, -1.2),
+ );
+
+ // the divisor of the matrix
+ $divisor = array_sum(array_map('array_sum', $matrix));
+
+ // color offset
+ $offset = 0;
+
+ // sharpen image
+ imageconvolution($image, $matrix, $divisor, $offset);
+
+ }
+
+ // return the image's identifier
+ return $image;
+
+ }
+
+ /**
+ * Creates a new image from given image identifier having the extension as specified by {@link target_path}.
+ *
+ * @param $identifier identifier An image identifier
+ *
+ * @return boolean Returns TRUE on success or FALSE on error.
+ *
+ * If FALSE is returned, check the {@link error} property to see the error code.
+ *
+ * @access private
+ */
+ function _write_image($identifier)
+ {
+
+ // sharpen image if it's required
+ $this->_sharpen_image($identifier);
+
+ // image saving process goes according to required extension
+ switch ($this->target_type) {
+
+ // if GIF
+ case 'gif':
+
+ // if GD support for this file type is not available
+ // in version 1.6 of GD the support for GIF files was dropped see
+ // http://php.net/manual/en/function.imagegif.php#function.imagegif.notes
+ if (!function_exists('imagegif')) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 6;
+
+ return false;
+
+ // if, for some reason, file could not be created
+ } elseif (@!imagegif($identifier, $this->target_path)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 3;
+
+ return false;
+
+ }
+
+ break;
+
+ // if JPEG
+ case 'jpg':
+ case 'jpeg':
+
+ // if GD support for this file type is not available
+ if (!function_exists('imagejpeg')) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 6;
+
+ return false;
+
+ // if, for some reason, file could not be created
+ } elseif (@!imagejpeg($identifier, $this->target_path, $this->jpeg_quality)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 3;
+
+ return false;
+
+ }
+
+ break;
+
+ // if PNG
+ case 'png':
+
+ // save full alpha channel information
+ imagesavealpha($identifier, true);
+
+ // if GD support for this file type is not available
+ if (!function_exists('imagepng')) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 6;
+
+ return false;
+
+ // if, for some reason, file could not be created
+ } elseif (@!imagepng($identifier, $this->target_path, $this->png_compression)) {
+
+ // save the error level and stop the execution of the script
+ $this->error = 3;
+
+ return false;
+
+ }
+
+ break;
+
+ // if not a supported file extension
+ default:
+
+ // save the error level and stop the execution of the script
+ $this->error = 5;
+
+ return false;
+
+ }
+
+ // get a list of functions disabled via configuration
+ $disabled_functions = @ini_get('disable_functions');
+
+ // if the 'chmod' function is not disabled via configuration
+ if ($disabled_functions == '' || strpos('chmod', $disabled_functions) === false) {
+
+ // chmod the file
+ chmod($this->target_path, intval($this->chmod_value, 8));
+
+ // save the error level
+ } else $this->error = 8;
+
+ // if target file has to have the same timestamp as the source image
+ if ($this->preserve_time && isset($this->source_image_time)) {
+
+ // touch the newly created file
+ @touch($this->target_path, $this->source_image_time);
+
+ }
+
+ // return true
+ return true;
+
+ }
+
+}
diff --git a/css/jasny-bootstrap.min.css b/css/jasny-bootstrap.min.css
new file mode 100644
index 0000000..58d244f
--- /dev/null
+++ b/css/jasny-bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Jasny Bootstrap v3.1.0 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
+
+@media (min-width:1px){.container-smooth{max-width:1170px}}.btn-labeled{padding-top:0;padding-bottom:0}.btn-label{position:relative;background:0 0;background:rgba(0,0,0,.15);display:inline-block;padding:6px 12px;left:-12px;border-radius:3px 0 0 3px}.btn-label.btn-label-right{left:auto;right:-12px;border-radius:0 3px 3px 0}.btn-lg .btn-label{padding:10px 16px;left:-16px;border-radius:5px 0 0 5px}.btn-lg .btn-label.btn-label-right{left:auto;right:-16px;border-radius:0 5px 5px 0}.btn-sm .btn-label{padding:5px 10px;left:-10px;border-radius:2px 0 0 2px}.btn-sm .btn-label.btn-label-right{left:auto;right:-10px;border-radius:0 2px 2px 0}.btn-xs .btn-label{padding:1px 5px;left:-5px;border-radius:2px 0 0 2px}.btn-xs .btn-label.btn-label-right{left:auto;right:-5px;border-radius:0 2px 2px 0}.nav-tabs-bottom{border-bottom:0;border-top:1px solid #ddd}.nav-tabs-bottom>li{margin-bottom:0;margin-top:-1px}.nav-tabs-bottom>li>a{border-radius:0 0 4px 4px}.nav-tabs-bottom>li>a:hover,.nav-tabs-bottom>li>a:focus,.nav-tabs-bottom>li.active>a,.nav-tabs-bottom>li.active>a:hover,.nav-tabs-bottom>li.active>a:focus{border:1px solid #ddd;border-top-color:transparent}.nav-tabs-left{border-bottom:0;border-right:1px solid #ddd}.nav-tabs-left>li{margin-bottom:0;margin-right:-1px;float:none}.nav-tabs-left>li>a{border-radius:4px 0 0 4px;margin-right:0;margin-bottom:2px}.nav-tabs-left>li>a:hover,.nav-tabs-left>li>a:focus,.nav-tabs-left>li.active>a,.nav-tabs-left>li.active>a:hover,.nav-tabs-left>li.active>a:focus{border:1px solid #ddd;border-right-color:transparent}.row>.nav-tabs-left{padding-right:0;padding-left:15px;margin-right:-1px;position:relative;z-index:1}.row>.nav-tabs-left+.tab-content{border-left:1px solid #ddd}.nav-tabs-right{border-bottom:0;border-left:1px solid #ddd}.nav-tabs-right>li{margin-bottom:0;margin-left:-1px;float:none}.nav-tabs-right>li>a{border-radius:0 4px 4px 0;margin-left:0;margin-bottom:2px}.nav-tabs-right>li>a:hover,.nav-tabs-right>li>a:focus,.nav-tabs-right>li.active>a,.nav-tabs-right>li.active>a:hover,.nav-tabs-right>li.active>a:focus{border:1px solid #ddd;border-left-color:transparent}.row>.nav-tabs-right{padding-left:0;padding-right:15px}.navmenu,.navbar-offcanvas{width:300px;height:100%;border-width:1px;border-style:solid;border-radius:4px}.navmenu-fixed-left,.navmenu-fixed-right,.navbar-offcanvas{position:fixed;z-index:1030;top:0;border-radius:0}.navmenu-fixed-left,.navbar-offcanvas{left:0;border-width:0 1px 0 0}.navmenu-fixed-right{right:0;border-width:0 0 0 1px}.navmenu-nav{margin-bottom:10px}.navmenu-nav.dropdown-menu{position:static;margin:0;padding-top:0;float:none;border:0;-webkit-box-shadow:none;box-shadow:none;border-radius:0}.navbar-offcanvas .navbar-nav{margin:0}@media (min-width:768px){.navbar-offcanvas{width:auto;border-top:0;box-shadow:none}.navbar-offcanvas.offcanvas{position:static;display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-offcanvas .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-offcanvas .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-offcanvas .navmenu-brand{display:none}}.navmenu-brand{display:block;font-size:18px;line-height:20px;padding:10px 15px;margin:10px 0}.navmenu-brand:hover,.navmenu-brand:focus{text-decoration:none}.navmenu-default,.navbar-default .navbar-offcanvas{background-color:#f8f8f8;border-color:#e7e7e7}.navmenu-default .navmenu-brand,.navbar-default .navbar-offcanvas .navmenu-brand{color:#777}.navmenu-default .navmenu-brand:hover,.navbar-default .navbar-offcanvas .navmenu-brand:hover,.navmenu-default .navmenu-brand:focus,.navbar-default .navbar-offcanvas .navmenu-brand:focus{color:#5e5e5e;background-color:transparent}.navmenu-default .navmenu-text,.navbar-default .navbar-offcanvas .navmenu-text{color:#777}.navmenu-default .navmenu-nav>.dropdown>a:hover .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a:hover .caret,.navmenu-default .navmenu-nav>.dropdown>a:focus .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navmenu-default .navmenu-nav>.open>a,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a,.navmenu-default .navmenu-nav>.open>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:hover,.navmenu-default .navmenu-nav>.open>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:focus{background-color:#e7e7e7;color:#555}.navmenu-default .navmenu-nav>.open>a .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a .caret,.navmenu-default .navmenu-nav>.open>a:hover .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:hover .caret,.navmenu-default .navmenu-nav>.open>a:focus .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navmenu-default .navmenu-nav>.dropdown>a .caret,.navbar-default .navbar-offcanvas .navmenu-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}.navmenu-default .navmenu-nav.dropdown-menu,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu{background-color:#e7e7e7}.navmenu-default .navmenu-nav.dropdown-menu>.divider,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.divider{background-color:#f8f8f8}.navmenu-default .navmenu-nav.dropdown-menu>.active>a,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a,.navmenu-default .navmenu-nav.dropdown-menu>.active>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:hover,.navmenu-default .navmenu-nav.dropdown-menu>.active>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:focus{background-color:#d7d7d7}.navmenu-default .navmenu-nav>li>a,.navbar-default .navbar-offcanvas .navmenu-nav>li>a{color:#777}.navmenu-default .navmenu-nav>li>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>li>a:hover,.navmenu-default .navmenu-nav>li>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>li>a:focus{color:#333;background-color:transparent}.navmenu-default .navmenu-nav>.active>a,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a,.navmenu-default .navmenu-nav>.active>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a:hover,.navmenu-default .navmenu-nav>.active>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navmenu-default .navmenu-nav>.disabled>a,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a,.navmenu-default .navmenu-nav>.disabled>a:hover,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a:hover,.navmenu-default .navmenu-nav>.disabled>a:focus,.navbar-default .navbar-offcanvas .navmenu-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navmenu-inverse,.navbar-inverse .navbar-offcanvas{background-color:#222;border-color:#080808}.navmenu-inverse .navmenu-brand,.navbar-inverse .navbar-offcanvas .navmenu-brand{color:#999}.navmenu-inverse .navmenu-brand:hover,.navbar-inverse .navbar-offcanvas .navmenu-brand:hover,.navmenu-inverse .navmenu-brand:focus,.navbar-inverse .navbar-offcanvas .navmenu-brand:focus{color:#fff;background-color:transparent}.navmenu-inverse .navmenu-text,.navbar-inverse .navbar-offcanvas .navmenu-text{color:#999}.navmenu-inverse .navmenu-nav>.dropdown>a:hover .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a:hover .caret,.navmenu-inverse .navmenu-nav>.dropdown>a:focus .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navmenu-inverse .navmenu-nav>.open>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a,.navmenu-inverse .navmenu-nav>.open>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:hover,.navmenu-inverse .navmenu-nav>.open>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:focus{background-color:#080808;color:#fff}.navmenu-inverse .navmenu-nav>.open>a .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a .caret,.navmenu-inverse .navmenu-nav>.open>a:hover .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:hover .caret,.navmenu-inverse .navmenu-nav>.open>a:focus .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navmenu-inverse .navmenu-nav>.dropdown>a .caret,.navbar-inverse .navbar-offcanvas .navmenu-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navmenu-inverse .navmenu-nav.dropdown-menu,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu{background-color:#080808}.navmenu-inverse .navmenu-nav.dropdown-menu>.divider,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.divider{background-color:#222}.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a,.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:hover,.navmenu-inverse .navmenu-nav.dropdown-menu>.active>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu>.active>a:focus{background-color:#000}.navmenu-inverse .navmenu-nav>li>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a{color:#999}.navmenu-inverse .navmenu-nav>li>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a:hover,.navmenu-inverse .navmenu-nav>li>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>li>a:focus{color:#fff;background-color:transparent}.navmenu-inverse .navmenu-nav>.active>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a,.navmenu-inverse .navmenu-nav>.active>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a:hover,.navmenu-inverse .navmenu-nav>.active>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.active>a:focus{color:#fff;background-color:#080808}.navmenu-inverse .navmenu-nav>.disabled>a,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a,.navmenu-inverse .navmenu-nav>.disabled>a:hover,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a:hover,.navmenu-inverse .navmenu-nav>.disabled>a:focus,.navbar-inverse .navbar-offcanvas .navmenu-nav>.disabled>a:focus{color:#444;background-color:transparent}.alert-fixed-top,.alert-fixed-bottom{position:fixed;width:100%;z-index:1035;border-radius:0;margin:0;left:0}@media (min-width:992px){.alert-fixed-top,.alert-fixed-bottom{width:992px;left:50%;margin-left:-496px}}.alert-fixed-top{top:0;border-width:0 0 1px}@media (min-width:992px){.alert-fixed-top{border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-width:0 1px 1px}}.alert-fixed-bottom{bottom:0;border-width:1px 0 0}@media (min-width:992px){.alert-fixed-bottom{border-top-right-radius:4px;border-top-left-radius:4px;border-width:1px 1px 0}}.offcanvas{display:none}.offcanvas.in{display:block}@media (max-width:767px){.offcanvas-xs{display:none}.offcanvas-xs.in{display:block}}@media (max-width:991px){.offcanvas-sm{display:none}.offcanvas-sm.in{display:block}}@media (max-width:1199px){.offcanvas-md{display:none}.offcanvas-md.in{display:block}}.offcanvas-lg{display:none}.offcanvas-lg.in{display:block}.canvas-sliding{-webkit-transition:top .35s,left .35s,bottom .35s,right .35s;transition:top .35s,left .35s,bottom .35s,right .35s}.offcanvas-clone{height:0!important;width:0!important;overflow:hidden!important;border:0!important;margin:0!important;padding:0!important;position:absolute!important;top:auto!important;left:auto!important;bottom:0!important;right:0!important;opacity:0!important}.table.rowlink td:not(.rowlink-skip),.table .rowlink td:not(.rowlink-skip){cursor:pointer}.table.rowlink td:not(.rowlink-skip) a,.table .rowlink td:not(.rowlink-skip) a{color:inherit;font:inherit;text-decoration:inherit}.table-hover.rowlink tr:hover td,.table-hover .rowlink tr:hover td{background-color:#cfcfcf}.btn-file{overflow:hidden;position:relative;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;opacity:0;filter:alpha(opacity=0);transform:translate(-300px,0) scale(4);font-size:23px;height:100%;direction:ltr;cursor:pointer}.fileinput{margin-bottom:9px;display:inline-block}.fileinput .form-control{padding-top:7px;padding-bottom:5px;display:inline-block;margin-bottom:0;vertical-align:middle;cursor:text}.fileinput .thumbnail{overflow:hidden;display:inline-block;margin-bottom:5px;vertical-align:middle;text-align:center}.fileinput .thumbnail>img{max-height:100%}.fileinput .btn{vertical-align:middle}.fileinput-exists .fileinput-new,.fileinput-new .fileinput-exists{display:none}.fileinput-inline .fileinput-controls{display:inline}.fileinput-filename{vertical-align:middle;display:inline-block;overflow:hidden}.form-control .fileinput-filename{vertical-align:bottom}.fileinput-new .input-group .btn-file{border-radius:0 4px 4px 0}.fileinput-new .input-group .btn-file.btn-xs,.fileinput-new .input-group .btn-file.btn-sm{border-radius:0 3px 3px 0}.fileinput-new .input-group .btn-file.btn-lg{border-radius:0 6px 6px 0}.form-group.has-warning .fileinput .fileinput-preview{color:#8a6d3b}.form-group.has-warning .fileinput .thumbnail{border-color:#faebcc}.form-group.has-error .fileinput .fileinput-preview{color:#a94442}.form-group.has-error .fileinput .thumbnail{border-color:#ebccd1}.form-group.has-success .fileinput .fileinput-preview{color:#3c763d}.form-group.has-success .fileinput .thumbnail{border-color:#d6e9c6}.input-group-addon:not(:first-child){border-left:0}
\ No newline at end of file
diff --git a/css/jasny-bootstrap.min.js b/css/jasny-bootstrap.min.js
new file mode 100644
index 0000000..05b3b05
--- /dev/null
+++ b/css/jasny-bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Jasny Bootstrap v3.1.0 (http://jasny.github.io/bootstrap)
+ * Copyright 2012-2014 Arnold Daniels
+ * Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Jasny Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.state=null,this.options.recalc&&(this.calcClone(),a(window).on("resize",a.proxy(this.recalc,this))),this.options.autohide&&a(document).on("click",a.proxy(this.autohide,this)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0,placement:"left",autohide:!0,recalc:!0},b.prototype.offset=function(){switch(this.options.placement){case"left":case"right":return this.$element.outerWidth();case"top":case"bottom":return this.$element.outerHeight()}},b.prototype.calcPlacement=function(){function b(a,b){if("auto"===e.css(b))return a;if("auto"===e.css(a))return b;var c=parseInt(e.css(a),10),d=parseInt(e.css(b),10);return c>d?b:a}var c=a(window).width()/this.$element.width(),d=a(window).height()/this.$element.height();this.$element.hasClass("in")||this.$element.css("visiblity","hidden !important").addClass("in");var e=this.$element;this.options.placement=c>d?b("left","right"):b("top","bottom"),"hidden !important"===this.$element.css("visibility")&&this.$element.removeClass("in").css("visiblity","")},b.prototype.opposite=function(a){switch(a){case"top":return"bottom";case"left":return"right";case"bottom":return"top";case"right":return"left"}},b.prototype.getCanvasElements=function(){var b=this.options.canvas?a(this.options.canvas):this.$element,c=b.find("*").filter(function(){return"fixed"===a(this).css("position")}).not(this.options.exclude);return b.add(c)},b.prototype.slide=function(b,c,d){if(!a.support.transition){var e={};return e[this.options.placement]="+="+c,b.animate(e,350,d)}var f=this.options.placement,g=this.opposite(f);b.each(function(){"auto"!==a(this).css(f)&&a(this).css(f,(parseInt(a(this).css(f),10)||0)+c),"auto"!==a(this).css(g)&&a(this).css(g,(parseInt(a(this).css(g),10)||0)-c)}),this.$element.one(a.support.transition.end,d).emulateTransitionEnd(350)},b.prototype.disableScrolling=function(){var b=a("body").width(),c="padding-"+this.opposite(this.options.placement);if(void 0===a("body").data("offcanvas-style")&&a("body").data("offcanvas-style",a("body").attr("style")),a("body").css("overflow","hidden"),a("body").width()>b){var d=parseInt(a("body").css(c),10)+a("body").width()-b;setTimeout(function(){a("body").css(c,d)},1)}},b.prototype.show=function(){if(!this.state){var b=a.Event("show.bs.offcanvas");if(this.$element.trigger(b),!b.isDefaultPrevented()){"auto"===this.options.placement&&this.calcPlacement(),this.state="sliding";var c=this.getCanvasElements(),d=this.offset(),e=this.options.placement,f=this.opposite(e);c.addClass("canvas-sliding").each(function(){a(this).data("offcanvas-style",a(this).attr("style")||""),"static"===a(this).css("position")&&a(this).css("position","relative"),"auto"!==a(this).css(e)&&"0px"!==a(this).css(e)||"auto"!==a(this).css(f)&&"0px"!==a(this).css(f)||a(this).css(e,0)}),-1!==c.index(this.$element)&&this.$element.css(e,-1*d),this.disableScrolling();var g=function(){this.state="slid",c.removeClass("canvas-sliding").addClass("canvas-slid"),this.$element.trigger("shown.bs.offcanvas")};setTimeout(a.proxy(function(){this.$element.addClass("in"),this.slide(c,d,a.proxy(g,this))},this),1)}}},b.prototype.hide=function(){if("slid"===this.state){var b=a.Event("hide.bs.offcanvas");if(this.$element.trigger(b),!b.isDefaultPrevented()){this.state="sliding";var c=a(".canvas-slid"),d=-1*this.offset(),e=function(){this.state=null,this.$element.removeClass("in"),c.removeClass("canvas-sliding"),c.add("body").each(function(){a(this).attr("style",a(this).data("offcanvas-style")).removeData("offcanvas-style")}),this.$element.trigger("hidden.bs.offcanvas")};c.removeClass("canvas-slid").addClass("canvas-sliding"),setTimeout(a.proxy(function(){this.slide(c,d,a.proxy(e,this))},this),1)}}},b.prototype.toggle=function(){"sliding"!==this.state&&this["slid"===this.state?"hide":"show"]()},b.prototype.calcClone=function(){this.$calcClone=this.$element.clone().html("").addClass("offcanvas-clone").removeClass("in").appendTo(a("body"))},b.prototype.recalc=function(){if("slid"===this.state()&&"none"!==this.$calcClone.css("display")){var b=-1*this.offset(),c=this.options.placement;this.getCanvasElements().each(function(){a(this).css(c,(parseInt(a(this).css(c),10)||0)+b)}).removeClass("canvas-slid"),a("body").css("overflow",""),this.$element.css(c,"").removeClass("in canvas-slid")}},b.prototype.autohide=function(b){0===a(b.target).closest(this.$element).length&&this.hide()};var c=a.fn.offcanvas;a.fn.offcanvas=function(c){return this.each(function(){var d=a(this),e=d.data("bs.offcanvas"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.offcanvas",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.offcanvas.Constructor=b,a.fn.offcanvas.noConflict=function(){return a.fn.offcanvas=c,this},a(document).on("click.bs.offcanvas.data-api","[data-toggle=offcanvas]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.offcanvas"),h=g?"toggle":d.data();b.stopPropagation(),g?g.toggle():f.offcanvas(h)})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.$element.on("click.bs.rowlink","td:not(.rowlink-skip)",a.proxy(this.click,this))};b.DEFAULTS={target:"a"},b.prototype.click=function(b){var c=a(b.currentTarget).closest("tr").find(this.options.target)[0];if(a(b.target)[0]!==c)if(b.preventDefault(),c.click)c.click();else if(document.createEvent){var d=document.createEvent("MouseEvents");d.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),c.dispatchEvent(d)}};var c=a.fn.rowlink;a.fn.rowlink=function(c){return this.each(function(){var d=a(this),e=d.data("rowlink");e||d.data("rowlink",e=new b(this,c))})},a.fn.rowlink.Constructor=b,a.fn.rowlink.noConflict=function(){return a.fn.rowlink=c,this},a(document).on("click.bs.rowlink.data-api",'[data-link="row"]',function(b){var c=a(this);c.data("rowlink")||(c.rowlink(c.data()),a(b.target).trigger("click.bs.rowlink"))})}(window.jQuery),+function(a){"use strict";var b=void 0!==window.orientation,c=navigator.userAgent.toLowerCase().indexOf("android")>-1,d="Microsoft Internet Explorer"==window.navigator.appName,e=function(b,d){c||(this.$element=a(b),this.options=a.extend({},e.DEFAULS,d),this.mask=String(this.options.mask),this.init(),this.listen(),this.checkVal())};e.DEFAULS={mask:"",placeholder:"_",definitions:{9:"[0-9]",a:"[A-Za-z]","?":"[A-Za-z0-9]","*":"."}},e.prototype.init=function(){var b=this.options.definitions,c=this.mask.length;this.tests=[],this.partialPosition=this.mask.length,this.firstNonMaskPos=null,a.each(this.mask.split(""),a.proxy(function(a,d){"?"==d?(c--,this.partialPosition=a):b[d]?(this.tests.push(new RegExp(b[d])),null===this.firstNonMaskPos&&(this.firstNonMaskPos=this.tests.length-1)):this.tests.push(null)},this)),this.buffer=a.map(this.mask.split(""),a.proxy(function(a){return"?"!=a?b[a]?this.options.placeholder:a:void 0},this)),this.focusText=this.$element.val(),this.$element.data("rawMaskFn",a.proxy(function(){return a.map(this.buffer,function(a,b){return this.tests[b]&&a!=this.options.placeholder?a:null}).join("")},this))},e.prototype.listen=function(){if(!this.$element.attr("readonly")){var b=(d?"paste":"input")+".mask";this.$element.on("unmask.bs.inputmask",a.proxy(this.unmask,this)).on("focus.bs.inputmask",a.proxy(this.focusEvent,this)).on("blur.bs.inputmask",a.proxy(this.blurEvent,this)).on("keydown.bs.inputmask",a.proxy(this.keydownEvent,this)).on("keypress.bs.inputmask",a.proxy(this.keypressEvent,this)).on(b,a.proxy(this.pasteEvent,this))}},e.prototype.caret=function(a,b){if(0!==this.$element.length){if("number"==typeof a)return b="number"==typeof b?b:a,this.$element.each(function(){if(this.setSelectionRange)this.setSelectionRange(a,b);else if(this.createTextRange){var c=this.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select()}});if(this.$element[0].setSelectionRange)a=this.$element[0].selectionStart,b=this.$element[0].selectionEnd;else if(document.selection&&document.selection.createRange){var c=document.selection.createRange();a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length}return{begin:a,end:b}}},e.prototype.seekNext=function(a){for(var b=this.mask.length;++a<=b&&!this.tests[a];);return a},e.prototype.seekPrev=function(a){for(;--a>=0&&!this.tests[a];);return a},e.prototype.shiftL=function(a,b){var c=this.mask.length;if(!(0>a)){for(var d=a,e=this.seekNext(b);c>d;d++)if(this.tests[d]){if(!(c>e&&this.tests[d].test(this.buffer[e])))break;this.buffer[d]=this.buffer[e],this.buffer[e]=this.options.placeholder,e=this.seekNext(e)}this.writeBuffer(),this.caret(Math.max(this.firstNonMaskPos,a))}},e.prototype.shiftR=function(a){for(var b=this.mask.length,c=a,d=this.options.placeholder;b>c;c++)if(this.tests[c]){var e=this.seekNext(c),f=this.buffer[c];if(this.buffer[c]=d,!(b>e&&this.tests[e].test(f)))break;d=f}},e.prototype.unmask=function(){this.$element.unbind(".mask").removeData("inputmask")},e.prototype.focusEvent=function(){this.focusText=this.$element.val();var a=this.mask.length,b=this.checkVal();this.writeBuffer();var c=this,d=function(){b==a?c.caret(0,b):c.caret(b)};d(),setTimeout(d,50)},e.prototype.blurEvent=function(){this.checkVal(),this.$element.val()!==this.focusText&&this.$element.trigger("change")},e.prototype.keydownEvent=function(a){var c=a.which;if(8==c||46==c||b&&127==c){var d=this.caret(),e=d.begin,f=d.end;return f-e===0&&(e=46!=c?this.seekPrev(e):f=this.seekNext(e-1),f=46==c?this.seekNext(f):f),this.clearBuffer(e,f),this.shiftL(e,f-1),!1}return 27==c?(this.$element.val(this.focusText),this.caret(0,this.checkVal()),!1):void 0},e.prototype.keypressEvent=function(a){var b=this.mask.length,c=a.which,d=this.caret();if(a.ctrlKey||a.altKey||a.metaKey||32>c)return!0;if(c){d.end-d.begin!==0&&(this.clearBuffer(d.begin,d.end),this.shiftL(d.begin,d.end-1));var e=this.seekNext(d.begin-1);if(b>e){var f=String.fromCharCode(c);if(this.tests[e].test(f)){this.shiftR(e),this.buffer[e]=f,this.writeBuffer();var g=this.seekNext(e);this.caret(g)}}return!1}},e.prototype.pasteEvent=function(){var a=this;setTimeout(function(){a.caret(a.checkVal(!0))},0)},e.prototype.clearBuffer=function(a,b){for(var c=this.mask.length,d=a;b>d&&c>d;d++)this.tests[d]&&(this.buffer[d]=this.options.placeholder)},e.prototype.writeBuffer=function(){return this.$element.val(this.buffer.join("")).val()},e.prototype.checkVal=function(a){for(var b=this.mask.length,c=this.$element.val(),d=-1,e=0,f=0;b>e;e++)if(this.tests[e]){for(this.buffer[e]=this.options.placeholder;f++