From 0c77b8e37a6e40414ccbf1299e5f5dbb54543878 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 22 Oct 2012 15:47:11 +0000 Subject: [PATCH] - Candidatos (sin terminar) git-svn-id: https://192.168.0.254/svn/Proyectos.Incam_PROFIND_Web/trunk@64 3fe1ab16-cfe0-e34b-8c9f-7d8c168d430d --- www/protected/config/main.php | 8 +- www/protected/config/mode_development.php | 10 +- .../controllers/CandidatoController.php | 194 + www/protected/data/tbl_productos.sql | 10 +- .../m121014_170834_tbl_estados_candidatos.php | 14 + ...5_tbl_idiomas_tecnologias_titulaciones.php | 38 + .../m121014_171033_tbl_candidatos.php | 53 + .../m121014_171456_tbl_candidatos_idiomas.php | 24 + ...014_171501_tbl_candidatos_titulaciones.php | 22 + www/protected/models/Candidato.php | 437 +++ www/protected/models/Idioma.php | 70 + www/protected/models/Tecnologia.php | 71 + www/protected/models/Titulacion.php | 71 + .../profind/css/aristo/images/bg_fallback.png | Bin 0 -> 3721 bytes .../profind/css/aristo/images/icon_sprite.png | Bin 0 -> 3217 bytes .../css/aristo/images/progress_bar.gif | Bin 0 -> 502 bytes .../css/aristo/images/slider_handles.png | Bin 0 -> 4453 bytes .../aristo/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../aristo/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes www/themes/profind/css/aristo/jquery-ui.css | 738 ++++ www/themes/profind/css/grid.css | 34 + www/themes/profind/css/media.css | 260 +- www/themes/profind/css/profind.css | 77 +- www/themes/profind/js/profind-general.js | 257 ++ www/themes/profind/lib/actual/.gitignore | 2 + www/themes/profind/lib/actual/CHANGELOG.md | 65 + www/themes/profind/lib/actual/LICENSE.txt | 20 + www/themes/profind/lib/actual/README.md | 107 + .../profind/lib/actual/jquery.actual.js | 97 + .../profind/lib/actual/jquery.actual.min.js | 8 + www/themes/profind/lib/actual/package.json | 25 + .../profind/lib/antiscroll/antiscroll.css | 54 + .../profind/lib/antiscroll/antiscroll.js | 446 +++ .../profind/lib/antiscroll/antiscroll.min.js | 446 +++ .../lib/antiscroll/deps/jquery-mousewheel.js | 78 + www/themes/profind/lib/antiscroll/index.html | 304 ++ www/themes/profind/lib/cookie/CHANGELOG.md | 17 + www/themes/profind/lib/cookie/README.md | 92 + .../profind/lib/cookie/jquery.cookie.js | 72 + www/themes/profind/lib/qtip2/jquery.qtip.css | 557 +++ www/themes/profind/lib/qtip2/jquery.qtip.js | 3270 +++++++++++++++++ .../profind/lib/qtip2/jquery.qtip.min.css | 1 + .../profind/lib/qtip2/jquery.qtip.min.js | 13 + www/themes/profind/lib/smartresize/README.md | 95 + .../lib/smartresize/jquery.debouncedresize.js | 47 + .../lib/smartresize/jquery.throttledresize.js | 58 + www/themes/profind/views/candidato/_form.php | 296 ++ www/themes/profind/views/candidato/_grid.php | 238 ++ www/themes/profind/views/candidato/create.php | 18 + www/themes/profind/views/candidato/index.php | 24 + www/themes/profind/views/candidato/update.php | 18 + www/themes/profind/views/layouts/main.php | 219 +- .../profind/views/sidebars/_menu_usuario.php | 54 + 53 files changed, 8901 insertions(+), 228 deletions(-) create mode 100644 www/protected/controllers/CandidatoController.php create mode 100644 www/protected/migrations/m121014_170834_tbl_estados_candidatos.php create mode 100644 www/protected/migrations/m121014_171025_tbl_idiomas_tecnologias_titulaciones.php create mode 100644 www/protected/migrations/m121014_171033_tbl_candidatos.php create mode 100644 www/protected/migrations/m121014_171456_tbl_candidatos_idiomas.php create mode 100644 www/protected/migrations/m121014_171501_tbl_candidatos_titulaciones.php create mode 100644 www/protected/models/Candidato.php create mode 100644 www/protected/models/Idioma.php create mode 100644 www/protected/models/Tecnologia.php create mode 100644 www/protected/models/Titulacion.php create mode 100644 www/themes/profind/css/aristo/images/bg_fallback.png create mode 100644 www/themes/profind/css/aristo/images/icon_sprite.png create mode 100644 www/themes/profind/css/aristo/images/progress_bar.gif create mode 100644 www/themes/profind/css/aristo/images/slider_handles.png create mode 100644 www/themes/profind/css/aristo/images/ui-icons_222222_256x240.png create mode 100644 www/themes/profind/css/aristo/images/ui-icons_454545_256x240.png create mode 100644 www/themes/profind/css/aristo/jquery-ui.css create mode 100644 www/themes/profind/css/grid.css create mode 100644 www/themes/profind/js/profind-general.js create mode 100644 www/themes/profind/lib/actual/.gitignore create mode 100644 www/themes/profind/lib/actual/CHANGELOG.md create mode 100644 www/themes/profind/lib/actual/LICENSE.txt create mode 100644 www/themes/profind/lib/actual/README.md create mode 100644 www/themes/profind/lib/actual/jquery.actual.js create mode 100644 www/themes/profind/lib/actual/jquery.actual.min.js create mode 100644 www/themes/profind/lib/actual/package.json create mode 100644 www/themes/profind/lib/antiscroll/antiscroll.css create mode 100644 www/themes/profind/lib/antiscroll/antiscroll.js create mode 100644 www/themes/profind/lib/antiscroll/antiscroll.min.js create mode 100644 www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js create mode 100644 www/themes/profind/lib/antiscroll/index.html create mode 100644 www/themes/profind/lib/cookie/CHANGELOG.md create mode 100644 www/themes/profind/lib/cookie/README.md create mode 100644 www/themes/profind/lib/cookie/jquery.cookie.js create mode 100644 www/themes/profind/lib/qtip2/jquery.qtip.css create mode 100644 www/themes/profind/lib/qtip2/jquery.qtip.js create mode 100644 www/themes/profind/lib/qtip2/jquery.qtip.min.css create mode 100644 www/themes/profind/lib/qtip2/jquery.qtip.min.js create mode 100644 www/themes/profind/lib/smartresize/README.md create mode 100644 www/themes/profind/lib/smartresize/jquery.debouncedresize.js create mode 100644 www/themes/profind/lib/smartresize/jquery.throttledresize.js create mode 100644 www/themes/profind/views/candidato/_form.php create mode 100644 www/themes/profind/views/candidato/_grid.php create mode 100644 www/themes/profind/views/candidato/create.php create mode 100644 www/themes/profind/views/candidato/index.php create mode 100644 www/themes/profind/views/candidato/update.php create mode 100644 www/themes/profind/views/sidebars/_menu_usuario.php diff --git a/www/protected/config/main.php b/www/protected/config/main.php index 183d274..8da5450 100644 --- a/www/protected/config/main.php +++ b/www/protected/config/main.php @@ -12,7 +12,6 @@ $config = array( 'sourceLanguage' => 'es', 'language' => 'es', 'name' => 'PROFIND', - 'defaultController' => 'usuario', // preloading 'log' component @@ -23,10 +22,8 @@ $config = array( // Modelos 'application.models.*', 'application.models.formularios.*', - // Helpers 'application.helpers.*', - // Componentes y extensiones 'application.components.*', 'application.extensions.yii-mail.YiiMailMessage', @@ -58,7 +55,12 @@ $config = array( 'errorAction' => 'site/error', ), ), + 'params' => array( + 'salarios_candidatos' => array( + 'salario_minimo' => 12000, + 'salario_maximo' => 60000, + ), 'phpass' => array( 'iteration_count_log2' => 8, 'portable_hashes' => false, diff --git a/www/protected/config/mode_development.php b/www/protected/config/mode_development.php index 96df857..2d3f1c4 100644 --- a/www/protected/config/mode_development.php +++ b/www/protected/config/mode_development.php @@ -49,6 +49,8 @@ $configSpecific = array( 'port' => 25, ), 'viewPath' => 'application.views.mails', + 'logging' => true, + 'dryRun' => false ), 'socialConnect' => array( 'class' => 'application.extensions.yii-socialconnect.YiiSocialConnect', @@ -87,14 +89,14 @@ $configSpecific = array( // Save log messages on file array( 'class' => 'CFileLogRoute', - 'levels' => 'error, trace', - 'categories' => 'application.*', + 'levels' => 'error, warning, trace, info', + //'categories' => 'application.*', ), // Show log messages on web pages array( 'class' => 'CWebLogRoute', - 'levels' => 'error, trace', - 'categories' => 'application.*', + 'levels' => 'error, warning, trace', + //'categories' => 'application.*', 'showInFireBug' => true, ), ), diff --git a/www/protected/controllers/CandidatoController.php b/www/protected/controllers/CandidatoController.php new file mode 100644 index 0000000..52815f2 --- /dev/null +++ b/www/protected/controllers/CandidatoController.php @@ -0,0 +1,194 @@ + array('index', 'view', 'create', 'update', 'delete', 'admin', 'updateEstado'), + 'users' => array('@'), + ), + ); + } + + /** + * Displays a particular model. + * @param integer $id the ID of the model to be displayed + */ + public function actionView($id) { + $this->render('view', array( + 'model' => $this->loadModel($id), + )); + } + + /** + * Creates a new model. + * If creation is successful, the browser will be redirected to the 'view' page. + */ + public function actionCreate() { + $candidato = new Candidato; + + // Uncomment the following line if AJAX validation is needed + // $this->performAjaxValidation($model); + + if (isset($_POST['Candidato'])) { + $candidato->attributes = $_POST['Candidato']; + if ($candidato->save()) + $this->redirect(array('index')); + } + + $this->render('create', array( + 'candidato' => $candidato, + )); + } + + /** + * @brief Modificar un candidato. + * @param integer $id el ID del candidato a modificar + */ + public function actionUpdate($id) { + + $candidato = $this->loadModel($id); + + // Uncomment the following line if AJAX validation is needed + // $this->performAjaxValidation($candidato); + + if (isset($_POST['Candidato'])) { + $candidato->attributes = $_POST['Candidato']; + $ficheroFotografia = CUploadedFile::getInstance($candidato, 'ficheroFotografia'); + + $quitarFotografia = Yii::app()->request->getParam('quitar_fotografia', '0'); + + if ($candidato->save()) { + if (($quitarFotografia == '1') && ($candidato->fotografia->tieneFotografia())) + $candidato->fotografia->eliminarFotografia(); + + if ($ficheroFotografia) + $candidato->fotografia->guardarFotografia($ficheroFotografia); + + Yii::app()->user->setFlash('success', Yii::t('profind', 'Se ha actualizado el candidato')); + $this->redirect(array('index')); + } + } + + $this->render('update', array( + 'candidato' => $candidato, + )); + } + + + public function actionUpdateEstado($id) { + + $model = $this->loadModel($id); + + // Uncomment the following line if AJAX validation is needed + $this->performAjaxValidation($model); + + if (isset($_GET['ajax'])) + var_dump($_GET['ajax']); + + if (isset($_POST['Candidato'])) { + $model->id_estado = $_POST['Candidato']['id_estado']; + + if ($model->save()) { + + } else { + + } + } else { + echo $this->renderPartial('_form_estado', array('model' => $model, false, true)); + } + } + + /** + * Deletes a particular model. + * If deletion is successful, the browser will be redirected to the 'admin' page. + * @param integer $id the ID of the model to be deleted + */ + public function actionDelete($id) { + if (Yii::app()->request->isPostRequest) { + // we only allow deletion via POST request + $this->loadModel($id)->delete(); + $this->borrarFoto($id); + Yii::app()->user->setFlash('success', "Candidato eliminardo correctamente."); + // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser + if (!isset($_GET['ajax'])) + $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('index')); + } + else + throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.'); + } + + /** + * @brief Lista todos los candidatos + * + */ + public function actionIndex() { + $candidatos = new Candidato('search'); + $candidatos->unsetAttributes(); // clear any default values + + if (isset($_GET['Candidato'])) + $candidatos->attributes = $_GET['Candidato']; + + $this->render('index', array( + 'candidatos' => $candidatos)); + } + + public function actionHistorial($id) { + $this->layout = '//layouts/candidato'; + $this->render('historial', array( + 'model' => $this->loadModel($id), + )); + } + + /** + * Manages all models. + */ + public function actionAdmin() { + $model = new Candidato('search'); + $model->unsetAttributes(); // clear any default values + if (isset($_GET['Candidato'])) + $model->attributes = $_GET['Candidato']; + + $this->render('admin', array( + 'model' => $model, + )); + } + + /** + * @brief Devuelve los datos del candidato con id $id. + * Si el candidato no existe, se lanza una excepción HTTP 404 + * @param integer $id el ID del candidato a recuperar + */ + public function loadModel($id) { + Yii::trace('Cargar el modelo', 'application.controllers.CandidatoController'); + $model = Candidato::model()->findByPk($id); + if ($model === null) + throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.')); + + return $model; + } + +} + +?> \ No newline at end of file diff --git a/www/protected/data/tbl_productos.sql b/www/protected/data/tbl_productos.sql index 395a4b6..4a9e047 100644 --- a/www/protected/data/tbl_productos.sql +++ b/www/protected/data/tbl_productos.sql @@ -1,3 +1,7 @@ -INSERT INTO `tbl_productos` (`id`, `titulo`, `n_agentes`, `n_publicaciones`) VALUES -(1, '1 Publicación - Gratis', NULL, 1), -(2, 'Hasta 5 Agentes - 500 euros/mes', 5, NULL); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(1, '1 Publicación - Gratis', 'PERSONAL', '0.00', '0', '1', 1); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(2, '5 agentes', 'EQUIPO', '500.00', '5', '-1', 0); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(3, '5 publicaciones', 'PERSONAL', '80.00', '0', '5', 0); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(4, '10 publicaciones', 'PERSONAL', '120.00', '0', '10', 0); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(5, '20 publicaciones', 'PERSONAL', '180.00', '0', '20', 0); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(6, 'Hasta 10 agentes', 'EQUIPO', '800.00', '10', '-1', 0); +INSERT INTO `tbl_productos` (`id`, `titulo`, `tipo`, `coste_mensual`, `max_agentes`, `max_publicaciones`, `predeterminado`) VALUES(7, 'Hasta 20 agentes', 'EQUIPO', '1200.00', '20', '-1', 0); diff --git a/www/protected/migrations/m121014_170834_tbl_estados_candidatos.php b/www/protected/migrations/m121014_170834_tbl_estados_candidatos.php new file mode 100644 index 0000000..b70b1cb --- /dev/null +++ b/www/protected/migrations/m121014_170834_tbl_estados_candidatos.php @@ -0,0 +1,14 @@ +createTable('tbl_estados_candidatos', array( + 'id' => 'pk', + 'descripcion' => 'string NOT NULL', + )); + } + + public function safeDown() { + $this->dropTable('tbl_estados_candidatos'); + } +} +?> \ No newline at end of file diff --git a/www/protected/migrations/m121014_171025_tbl_idiomas_tecnologias_titulaciones.php b/www/protected/migrations/m121014_171025_tbl_idiomas_tecnologias_titulaciones.php new file mode 100644 index 0000000..6c8ea2f --- /dev/null +++ b/www/protected/migrations/m121014_171025_tbl_idiomas_tecnologias_titulaciones.php @@ -0,0 +1,38 @@ +createTable('tbl_idiomas', array( + 'id' => 'pk', + 'descripcion' => 'string NOT NULL', + )); + + $this->createTable('tbl_tecnologias', array( + 'id' => 'pk', + 'descripcion' => 'string NOT NULL', + )); + + $this->createTable('tbl_perfiles_tecnicos', array( + 'id' => 'pk', + 'descripcion' => 'string NOT NULL', + )); + + $this->createTable('tbl_perfiles_funcionales', array( + 'id' => 'pk', + 'descripcion' => 'string NOT NULL', + )); + } + + public function safeDown() { + $this->dropTable('tbl_perfiles_tecnicos'); + + $this->dropTable('tbl_perfiles_funcionales'); + + $this->dropTable('tbl_tecnologias'); + + $this->dropTable('tbl_idiomas'); + } + +} +?> \ No newline at end of file diff --git a/www/protected/migrations/m121014_171033_tbl_candidatos.php b/www/protected/migrations/m121014_171033_tbl_candidatos.php new file mode 100644 index 0000000..9e63ab4 --- /dev/null +++ b/www/protected/migrations/m121014_171033_tbl_candidatos.php @@ -0,0 +1,53 @@ +createTable('tbl_candidatos', array( + 'id' => 'pk', + 'id_estado' => 'integer', + + 'n_identificacion' => 'string', + 'nombre' => 'string', + 'apellidos' => 'string', + 'email' => 'string', + 'telefono_fijo' => 'string', + 'telefono_movil' => 'string', + 'sexo' => 'string', + 'localidad' => 'string', + + 'fecha_nacimiento' => 'date', + 'lugar_nacimiento' => 'string', + + 'created_time' => 'datetime', + 'modified_time' => 'datetime', + 'deleted_time' => 'datetime', + + // Carnet de conducir + 'carnet_conducir' => 'string', + 'vehiculo_propio' => 'boolean', + + // Observaciones + 'observaciones' => 'text', + + // Rango de salarios + 'salario_minimo' => 'integer', + 'salario_maximo' => 'integer', + + // Procedencia del candidato + 'procedencia' => 'string', + + // Disponibilidades + 'disponibilidad_incorporacion' => 'string', + 'disponibilidad_entrevistas' => 'string', + 'disponibilidad_guardias' => 'string', + 'disponibilidad_viajar' => 'string', + 'disponibilidad_proyectos_internacionales' => 'string', + )); + } + + public function safeDown() { + $this->dropTable('tbl_candidatos'); + } + +} \ No newline at end of file diff --git a/www/protected/migrations/m121014_171456_tbl_candidatos_idiomas.php b/www/protected/migrations/m121014_171456_tbl_candidatos_idiomas.php new file mode 100644 index 0000000..3867b4f --- /dev/null +++ b/www/protected/migrations/m121014_171456_tbl_candidatos_idiomas.php @@ -0,0 +1,24 @@ +createTable('tbl_candidatos_idiomas', array( + 'id' => 'pk', + 'candidato_id' => 'integer NOT NULL', + 'idioma' => 'string NOT NULL', + 'conversacion' => 'string', + 'lectura_traduccion' => 'string', + )); + + $this->addForeignKey('fk_candidatos_idiomas_1', 'tbl_candidatos_idiomas', 'candidato_id', 'tbl_candidatos', 'id', 'CASCADE', 'CASCADE'); + } + + public function safeDown() { + $this->dropForeignKey('fk_candidatos_idiomas_1', 'tbl_candidatos_idiomas'); + $this->dropTable('tbl_candidatos_idiomas'); + } + +} + +?> \ No newline at end of file diff --git a/www/protected/migrations/m121014_171501_tbl_candidatos_titulaciones.php b/www/protected/migrations/m121014_171501_tbl_candidatos_titulaciones.php new file mode 100644 index 0000000..002c33a --- /dev/null +++ b/www/protected/migrations/m121014_171501_tbl_candidatos_titulaciones.php @@ -0,0 +1,22 @@ +createTable('tbl_candidatos_titulaciones', array( + 'id' => 'pk', + 'candidato_id' => 'integer NOT NULL', + 'titulacion' => 'string NOT NULL', + )); + + $this->addForeignKey('fk_candidatos_titulaciones_1', 'tbl_candidatos_titulaciones', 'candidato_id', 'tbl_candidatos', 'id', 'CASCADE', 'CASCADE'); + } + + public function safeDown() { + $this->dropForeignKey('fk_candidatos_titulaciones_1', 'tbl_candidatos_titulaciones'); + $this->dropTable('tbl_candidatos_titulaciones'); + } + +} + +?> \ No newline at end of file diff --git a/www/protected/models/Candidato.php b/www/protected/models/Candidato.php new file mode 100644 index 0000000..bb6ed14 --- /dev/null +++ b/www/protected/models/Candidato.php @@ -0,0 +1,437 @@ +nombreCompleto_search)) { + return $this->nombreCompleto_search; + } + + $this->nombreCompleto_search = $this->nombre . ' ' . $this->apellidos; + return $this->nombreCompleto_search; + } + + public function getRangoSalarial() { + return Yii::app()->numberFormatter->formatCurrency($this->salario_minimo, 'EUR') . ' - ' . + Yii::app()->numberFormatter->formatCurrency($this->salario_maximo, 'EUR'); + } + + public function getTieneVehiculoPropio() { + return Yii::app()->format->boolean($this->vehiculo_propio); + } + + public function getNombreLocalidad() { + return Poblacion::model()->findByPk($this->localidad)->poblacion; + } + + public function getNombreCompletoLocalidad() { + $nombre = ''; + $poblacion = Poblacion::model()->with('provincia')->findByPk($this->localidad); + if (isset($poblacion)) { + $nombre = $poblacion->poblacion; + if (isset($poblacion->provincia)) { + $nombre .= ' (' . $poblacion->provincia->provincia . ')'; + } + } + return $nombre; + } + + /** + * Devuelve la lista de géneros de un candidato. + * @return array lista de géneros permitidos + */ + public function getOpcionesGenero() { + return array( + self::GENERO_HOMBRE => 'Hombre', + self::GENERO_MUJER => 'Mujer' + ); + } + + public function getCssClassEstado() { + return "estado" . array_search($this->id_estado, $this->opcionesEstado); + } + + /** + * Devuelve la lista de estados permitidos para un candidato. + * @return array lista de estados permitidos + */ + public function getOpcionesEstado() { + return array( + 0 => '510', + 1 => '511', + 2 => '520', + 3 => '530', + 4 => '540', + 5 => '560', + 6 => '600', + ); + } + + /** + * Returns the static model of the specified AR class. + * @param string $className active record class name. + * @return Candidato the static model class + */ + public static function model($className = __CLASS__) { + return parent::model($className); + } + + /** + * @return string the associated database table name + */ + public function tableName() { + return 'tbl_candidatos'; + } + + /** + * @return array validation rules for model attributes. + */ + public function rules() { + // NOTE: you should only define rules for those attributes that + // will receive user inputs. + return array( + array('nombre, email', 'required'), + array('email', 'unique'), + array('email', 'email'), + + array('ficheroFotografia', 'file', + 'types' => 'jpg', + 'maxSize' => 1024 * 1024 * 1, // 1MB como máximo + 'tooLarge' => Yii::t('profind', 'La imagen es demasiado pesada. Elija otra fotografía más pequeña.'), + 'wrongType' => Yii::t('profind', 'Sólo se permiten imágenes en formato JPG.'), + 'allowEmpty' => 'true', + ), + + array('salario_minimo, salario_maximo', 'numerical','allowEmpty' => 'true'), + + array('salario_minimo', 'default', 'value' => Yii::app()->params['salarios_candidatos']['salario_minimo']), + array('salario_maximo', 'default', 'value' => Yii::app()->params['salarios_candidatos']['salario_maximo']), + + array('n_identificacion, nombre, apellidos, email, telefono_fijo, + telefono_movil, sexo, lugar_nacimiento, localidad, + carnet_conducir, procedencia, disponibilidad_incorporacion, + disponibilidad_entrevistas, disponibilidad_guardias, + disponibilidad_viajar, + disponibilidad_proyectos_internacionales', + 'length', 'max' => 255), + + array('id_estado', 'numerical', 'integerOnly' => true), + array('fecha_nacimiento, observaciones', 'safe'), + array('fecha_nacimiento', 'date', 'format' => 'dd/MM/yyyy'), + + // The following rule is used by search(). + // Please remove those attributes that should not be searched. + array('id, id_estado, + nombre_estado_search, nombreCompleto_search, capacidad_tecnica_search, + idiomas_search, salario_ini_search, salario_fin_search, + tecnologias_search, funciones_search, + n_identificacion, email, telefono_fijo, + telefono_movil, sexo, fecha_nacimiento, lugar_nacimiento, + localidad, fecha_alta, usuario_alta, + usuario_modificacion, carnet_conducir, vehiculo_propio, + observaciones, salario_minimo, salario_maximo, procedencia, + disponibilidad_incorporacion, disponibilidad_entrevistas, + disponibilidad_guardias, disponibilidad_viajar, + disponibilidad_proyectos_internacionales', + 'safe', 'on' => 'search') + ); + } + + /** + * @return array relational rules. + */ + public function relations() { + return array( + //'capacidades' => array(self::HAS_MANY, 'CandidatoCapacidad', 'candidato_id'), + //'capacidadesCount' => array(self::STAT, 'CandidatoCapacidad', 'candidato_id'), + 'idiomas' => array(self::HAS_MANY, 'CandidatoIdioma', 'candidato_id'), + 'idiomasCount' => array(self::STAT, 'CandidatoIdioma', 'candidato_id'), + 'titulaciones' => array(self::HAS_MANY, 'CandidatoTitulacion', 'candidato_id'), + 'titulacionesCount' => array(self::STAT, 'CandidatoTitulacion', 'candidato_id'), + //'documentos' => array(self::HAS_MANY, 'CandidatoDocumento', 'candidato_id'), + //'documentosCount' => array(self::STAT, 'CandidatoDocumento', 'candidato_id'), + 'estados' => array(self::BELONGS_TO, 'EstadoCandidato', 'id_estado'), + ); + } + + /** + * @return array customized attribute labels (name=>label) + */ + public function attributeLabels() { + return array( + 'id' => 'ID', + 'id_estado' => 'ID estado', + 'nombre_estado_search' => 'Estado', + 'idiomas_search' => 'Idioma', + 'nombreApellidos' => 'Candidato', + 'foto' => 'Foto', + 'n_identificacion' => 'DNI/Pasaporte', + 'nombre' => 'Nombre', + 'apellidos' => 'Apellidos', + 'email' => 'Email', + 'telefono_fijo' => 'Teléfono fijo', + 'telefono_movil' => 'Teléfono móvil', + 'sexo' => 'Sexo', + 'fecha_nacimiento' => 'Fecha de nacimiento', + 'lugar_nacimiento' => 'Lugar de nacimiento', + 'localidad' => 'Localidad', + 'carnet_conducir' => 'Carnet de conducir', + 'vehiculo_propio' => 'Vehículo propio', + 'observaciones' => 'Observaciones', + 'salario_minimo' => 'Salario mínimo', + 'salario_maximo' => 'Salario máximo', + 'procedencia' => 'Procedencia', + 'disponibilidad_incorporacion' => 'Disponibilidad de incorportación', + 'disponibilidad_entrevistas' => 'Disponibilidad para entrevistas', + 'disponibilidad_guardias' => 'Disponibilidad para guardias', + 'disponibilidad_viajar' => 'Disponibilidad para viajar', + 'disponibilidad_proyectos_internacionales' => 'Disponibilidad para proyectos internacionales', + 'nombreCompleto_search' => 'Candidato', + 'observaciones' => 'Observaciones', + 'tecnologias_search' => 'Tecnologías', + 'funciones_search' => 'Perfiles funcionales', + ); + } + + /** + * Retrieves a list of models based on the current search/filter conditions. + * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. + */ + public function search() { + // Warning: Please modify the following code to remove attributes that + // should not be searched. + + $criteria=new CDbCriteria; + + $criteria->compare('id', $this->id); + $criteria->compare('id_estado', $this->id_estado); + $criteria->compare('n_identificacion', $this->n_identificacion, true); + $criteria->compare('nombre', $this->nombre, true); + $criteria->compare('apellidos', $this->apellidos, true); + $criteria->compare('email', $this->email, true); + $criteria->compare('telefono_fijo', $this->telefono_fijo, true); + $criteria->compare('telefono_movil', $this->telefono_movil, true); + $criteria->compare('sexo', $this->sexo, true); + $criteria->compare('localidad', $this->localidad, true); + $criteria->compare('fecha_nacimiento', $this->fecha_nacimiento, true); + $criteria->compare('lugar_nacimiento', $this->lugar_nacimiento, true); + $criteria->compare('created_time', $this->created_time, true); + $criteria->compare('modified_time', $this->modified_time, true); + $criteria->compare('deleted_time', $this->deleted_time, true); + $criteria->compare('carnet_conducir', $this->carnet_conducir, true); + $criteria->compare('vehiculo_propio', $this->vehiculo_propio); + $criteria->compare('observaciones', $this->observaciones, true); + $criteria->compare('salario_minimo', $this->salario_minimo); + $criteria->compare('salario_maximo', $this->salario_maximo); + $criteria->compare('procedencia', $this->procedencia, true); + $criteria->compare('disponibilidad_incorporacion', $this->disponibilidad_incorporacion, true); + $criteria->compare('disponibilidad_entrevistas', $this->disponibilidad_entrevistas, true); + $criteria->compare('disponibilidad_guardias', $this->disponibilidad_guardias, true); + $criteria->compare('disponibilidad_viajar', $this->disponibilidad_viajar, true); + $criteria->compare('disponibilidad_proyectos_internacionales', $this->disponibilidad_proyectos_internacionales, true); + + $sort = new CSort(); + $sort->attributes = array( + 'defaultOrder' => 'id', + 'nombreCompleto' => array( + 'asc' => 'concat(t.nombre, " ", t.apellidos)', + 'desc' => 'concat(t.nombre, " ", t.apellidos) desc', + ), + ); + return new CActiveDataProvider($this, array( + 'criteria'=>$criteria, + //'sort' => $sort, + )); + +// $sort = new CSort(); +// $sort->attributes = array( +// 'defaultOrder' => '', +// 'nombre_estado_search' => array( +// 'asc' => 'estados.descripcion', +// 'desc' => 'estados.descripcion DESC', +// ), +// 'fecha_modificacion' => array( +// 'asc' => 't.fecha_modificacion', +// 'desc' => 't.fecha_modificacion desc', +// ), +// 'nombreCompleto_search' => array( +// 'asc' => 'concat(t.nombre, " ", t.apellidos)', +// 'desc' => 'concat(t.nombre, " ", t.apellidos) desc', +// ), +// 'capacidad_tecnica_search' => array( +// 'asc' => 'capacidades.perfil_tecnico_id', +// 'desc' => 'capacidades.perfil_tecnico_id desc', +// ), +// ); +// echo $criteria->condition; +// return new CActiveDataProvider($this, array( +// 'criteria' => $criteria, +// 'sort' => $sort, +// )); + } + + protected function beforeValidate() { + if ($this->isNewRecord) { + $this->id_estado = 510; + $this->created_time = date('Y-m-d H:i:s', time()); + } else { + $this->modified_time = date('Y-m-d H:i:s', time()); + } + + return parent::beforeValidate(); + } + + protected function beforeSave() { + if ($this->isNewRecord) + $this->created_time = date("Y-m-d H:i:s"); + + /*if (($this->estado === self::ESTADO_BORRADO) && ($this->deleted_time === NULL)) + $this->deleted_time = date("Y-m-d H:i:s");*/ + + //PHP dates are displayed as dd/mm/yyyy + //MYSQL dates are stored as yyyy-mm-dd + if ($this->fecha_nacimiento != '') { + $dateToMySQL = date('Y-m-d', CDateTimeParser::parse($this->fecha_nacimiento, Yii::app()->locale->dateFormat)); + $this->fecha_nacimiento = $dateToMySQL; + } + + return parent::beforeSave(); + } + + protected function afterFind() { + $this->fotografia = new FotografiaPerfil(); + $this->fotografia->modelo = $this; + + //PHP dates are displayed as dd/mm/yyyy + //MYSQL dates are stored as yyyy-mm-dd + + $dateToLocale = Yii::app()->dateFormatter->formatDateTime(CDateTimeParser::parse($this->fecha_nacimiento, 'yyyy-MM-dd'), 'medium', null); + $this->fecha_nacimiento = $dateToLocale; + + parent::afterFind(); + } + + protected function afterSave() { + parent::afterSave(); + if ($this->isNewRecord) + $this->createUploadDir(); + } + + protected function afterDelete() { + parent::afterDelete(); + $this->deleteUploadDir(); + } + + protected function afterConstruct() { + parent::afterConstruct(); + + $this->fotografia = new FotografiaPerfil(); + $this->fotografia->modelo = $this; + } + + /** + * @brief Devuelve el nombre del fichero por defecto cuando no se tiene imagen + * @return string ruta + */ + public function getImagenDefault() { + return 'user_photo.jpg'; + } + + /** + * @brief Devuelve la ruta con los ficheros del usuario. + * Incluye el separador de directorios al final de la ruta. + * @return string ruta + */ + public function getUploadPath() { + return Yii::getPathOfAlias('application.uploads.candidatos') . DIRECTORY_SEPARATOR . $this->id . DIRECTORY_SEPARATOR; + } + + /** + * @brief Crea un directorio para almacenar ficheros del usuario + * @return boolean + */ + private function createUploadDir() { + $upload = $this->getUploadPath(); + + if(!is_dir($upload)) { + return mkdir($upload); + } + else return false; + } + + /** + * @brief Elimina el directorio del usuario y todos sus ficheros + * @return boolean + */ + private function deleteUploadDir() { + $upload = $this->getUploadPath(); + + if(is_dir($upload)) + return GHelper::recursiveRemoveDirectory($upload); + else return false; + } + +} + +?> \ No newline at end of file diff --git a/www/protected/models/Idioma.php b/www/protected/models/Idioma.php new file mode 100644 index 0000000..fab2f3b --- /dev/null +++ b/www/protected/models/Idioma.php @@ -0,0 +1,70 @@ + 255), + + array('id, descripcion', 'safe', 'on' => 'search'), + ); + } + + /** + * @return array etiquetas para los campos (campo=>etiqueta) + */ + public function attributeLabels() { + return array( + 'id' => 'ID', + 'descripcion' => 'Descripción', + ); + } + + /** + * Retrieves a list of models based on the current search/filter conditions. + * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. + */ + public function search() { + // Warning: Please modify the following code to remove attributes that + // should not be searched. + + $criteria = new CDbCriteria; + $criteria->compare('id', $this->id); + $criteria->compare('descripcion', $this->descripcion, true); + + $sort = new CSort; + $sort->defaultOrder = 'descripcion ASC'; + + return new CActiveDataProvider($this, array( + 'criteria' => $criteria, + 'sort' => $sort, + )); + } + +} +?> \ No newline at end of file diff --git a/www/protected/models/Tecnologia.php b/www/protected/models/Tecnologia.php new file mode 100644 index 0000000..dc88769 --- /dev/null +++ b/www/protected/models/Tecnologia.php @@ -0,0 +1,71 @@ + 255), + + array('id, descripcion', 'safe', 'on' => 'search'), + ); + } + + /** + * @return array etiquetas para los campos (campo=>etiqueta) + */ + public function attributeLabels() { + return array( + 'id' => 'ID', + 'descripcion' => 'Descripción', + ); + } + + /** + * Retrieves a list of models based on the current search/filter conditions. + * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. + */ + public function search() { + // Warning: Please modify the following code to remove attributes that + // should not be searched. + + $criteria = new CDbCriteria; + + $criteria->compare('id', $this->id); + $criteria->compare('descripcion', $this->descripcion, true); + + $sort = new CSort; + $sort->defaultOrder = 'descripcion ASC'; + + return new CActiveDataProvider($this, array( + 'criteria' => $criteria, + 'sort' => $sort, + )); + } + +} +?> \ No newline at end of file diff --git a/www/protected/models/Titulacion.php b/www/protected/models/Titulacion.php new file mode 100644 index 0000000..fea475e --- /dev/null +++ b/www/protected/models/Titulacion.php @@ -0,0 +1,71 @@ + 255), + + array('id, descripcion', 'safe', 'on' => 'search'), + ); + } + + /** + * @return array etiquetas para los campos (campo=>etiqueta) + */ + public function attributeLabels() { + return array( + 'id' => 'ID', + 'descripcion' => 'Descripción', + ); + } + + /** + * Retrieves a list of models based on the current search/filter conditions. + * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. + */ + public function search() { + // Warning: Please modify the following code to remove attributes that + // should not be searched. + + $criteria = new CDbCriteria; + $criteria->compare('id', $this->id); + $criteria->compare('descripcion', $this->descripcion, true); + + $sort = new CSort; + $sort->defaultOrder = 'descripcion ASC'; + + return new CActiveDataProvider($this, array( + 'criteria' => $criteria, + 'sort' => $sort, + )); + } + +} + +?> \ No newline at end of file diff --git a/www/themes/profind/css/aristo/images/bg_fallback.png b/www/themes/profind/css/aristo/images/bg_fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..4b2754b8040e4bb430bd910225bb9760d25e8794 GIT binary patch literal 3721 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 literal 0 HcmV?d00001 diff --git a/www/themes/profind/css/aristo/images/icon_sprite.png b/www/themes/profind/css/aristo/images/icon_sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..636c80f221621c2461cb2f78764b21a1d5ce2f5a GIT binary patch literal 3217 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 literal 0 HcmV?d00001 diff --git a/www/themes/profind/css/aristo/images/slider_handles.png b/www/themes/profind/css/aristo/images/slider_handles.png new file mode 100644 index 0000000000000000000000000000000000000000..b95a46eca97b9001da25067948cb05a0021be2a1 GIT binary patch literal 4453 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 literal 0 HcmV?d00001 diff --git a/www/themes/profind/css/aristo/images/ui-icons_222222_256x240.png b/www/themes/profind/css/aristo/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/www/themes/profind/css/aristo/images/ui-icons_454545_256x240.png b/www/themes/profind/css/aristo/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..59bd45b907c4fd965697774ce8c5fc6b2fd9c105 GIT binary patch literal 4369 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 li > a { - padding-top: 10px + padding-top: 10px; } - /* fixed layout */ - .profind-fixed { - max-width: 940px; + .gebo-fixed { margin: 0 auto; - } - .profind-fixed header .container-fluid { max-width: 940px; - margin: 0 auto; } - .profind-fixed #maincontainer { - border-right: 1px solid #ccc; + .gebo-fixed header .container-fluid { + margin: 0 auto; + max-width: 940px; + } + .gebo-fixed #maincontainer { border-left: 1px solid #ccc; + border-right: 1px solid #ccc; } - .profind-fixed .sidebar { + .gebo-fixed .sidebar { left: 50%; margin-left: -469px; } - .profind-fixed .brand { - width: 120px + .gebo-fixed .sidebar_switch { + left: 50%; + margin-left: -250px; + } + .gebo-fixed.sidebar_hidden .sidebar_switch { + left: 50%; + margin-left: -465px; + } + .gebo-fixed .search_page .box_view .search_item { + height: 210px; + margin: 0 0 2% 2%; + width: 48%; + } + .gebo-fixed .activeMediaTable th.optional,.gebo-fixed .activeMediaTable td.optional { + display: none; + } + .gebo-fixed .brand { + width: 120px; } .sidebar_right #maincontainer { - background-image: url(../images/main_bg_right.gif); + background-image: url(../img/main_bg_right.gif); background-position: right 0; } .sidebar_right .sidebar { @@ -53,120 +61,121 @@ right: 6px; } .sidebar_right .main_content { - margin-right: 240px; - margin-left: 0; border-left: none; + margin-left: 0; + margin-right: 240px; } .sidebar_right.sidebar_hidden #maincontainer { - background: #fff + background: #fff; } .sidebar_right.sidebar_hidden .main_content { - margin: 0 + margin: 0; } - .profind-fixed.sidebar_right .sidebar { + .gebo-fixed.sidebar_right .sidebar { left: auto; - right: 50%; margin-left: 0; margin-right: -470px; + right: 50%; } - .profind-fixed.sidebar_right .sidebar_switch { + .gebo-fixed.sidebar_right .sidebar_switch { left: auto; - right: 50%; margin-left: 0; margin-right: -465px; + right: 50%; } - .profind-fixed.sidebar_hidden.sidebar_right .sidebar_switch { - laeft: auto; + .gebo-fixed.sidebar_hidden.sidebar_right .sidebar_switch { + left: auto; margin-left: 0; margin-right: -465px; right: 50%; } } -@media (max-width: 1279px) { + +@media (max-width: 1279px) { .search_page .box_view .search_item { - width: 49% + width: 49%; } } -@media (max-width: 979px) { + +@media (max-width: 979px) { #maincontainer { - background: #fff + background: #fff; } - .row > [class*="span"], - .navbar-fixed-top { - margin: 0 !important + .row > [class*="span"],.navbar-fixed-top { + margin: 0 !important; } .navbar-fixed-top .container-fluid { - padding: 0 !important + padding: 0 !important; } .navbar .brand { - width: auto; line-height: 18px; margin: 3px 0 6px 34px; + width: auto; } .navbar .user_menu { - padding-top: 5px + padding-top: 5px; } .navbar .user_menu .dropdown-menu { - margin: 8px 10px 0 0 + margin: 8px 10px 0 0; } .navbar .user_menu > li > a { - padding: 0 10px 0 0 + padding: 0 10px 0 0; } .navbar-inner { + min-height: 28px; position: relative; z-index: 990; - min-height: 28px; } .nav-collapse a { - color: #fff !important + color: #fff !important; } .nav-collapse .dropdown-menu li { - padding: 0 + padding: 0; } .nav-collapse .dropdown-menu li a { - font-weight: 400 + font-weight: 400; } .nav-collapse .sub-menu { display: block; left: 0; - right: auto; position: relative; + right: auto; visibility: visible; } .nav-collapse .caret-right { - display: none + display: none; } .btn-navbar { margin-top: 2px !important; padding: 2px 8px !important; } .user_menu .dropdown { - margin-left: 10px + margin-left: 10px; } .main_content { - margin: 0 !important; border: none !important; + margin: 0 !important; padding: 28px 14px 20px; } .main_content .row-fluid + .row-fluid { - margin-top: 20px + margin-top: 20px; } .sidebar { + background: #f1f1f1; + border-color: #ccc; + border-radius: 0px 5px 5px 0px; + border-style: solid; + border-width: 0 1px; + box-shadow: 1px 1px 4px rgba(0,0,0,0.2); height: 400px; + left: 0; + margin: 0; + moz-box-shadow: 1px 1px 4px rgba(0,0,0,0.2); position: absolute; top: 39px; - left: 0; - background: #f1f1f1; - border-width: 0 1px; - border-style: solid; - border-color: #ccc; - margin: 0; - -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.2); - -moz-box-shadow: 1px 1px 4px rgba(0,0,0,0.2); - box-shadow: 1px 1px 4px rgba(0,0,0,0.2); + webkit-border-radius: 0px 5px 5px 0px; + webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.2); z-index: 1000; - -webkit-border-radius: 0px 5px 5px 0px; - border-radius: 0px 5px 5px 0px; } .sidebar:after { border-bottom: 6px solid #fff; @@ -179,154 +188,167 @@ top: -6px; } .sidebar_hidden .sidebar { - border: none + border: none; } .sidebar_switch { - position: absolute; - z-index: 1000; left: 5px !important; - top: 14px; padding: 0 10px; + position: absolute; + top: 14px; + z-index: 1000; } .off_switch { - background-position: center 1px + background-position: center 1px; } .on_switch { - background-position: center -17px + background-position: center -17px; } .sidebar_inner { - padding-bottom: 0 !important + padding-bottom: 0 !important; } div.sticky-queue { - z-index: 10000; top: 0; + z-index: 10000; } .ms-container { - background-position: 160px 83px + background-position: 160px 83px; } .ms-container ul.ms-list { - width: 152px + width: 152px; } #multi_search { - width: 136px + width: 136px; } .btn_menu { - display: block; - clear: both; - padding: 8px 0 6px; border-top: 1px solid rgba(255,255,255,.2); box-shadow: 0 -1px 0 rgba(0,0,0,.2); - text-align: center; - position: relative; - top: 4px; + clear: both; cursor: pointer; + display: block; + padding: 8px 0 6px; + position: relative; + text-align: center; + top: 4px; } .btn_menu span { - opacity: .8 + opacity: .8; } .ssw_trigger { - display: none + display: none; } } -@media (max-width: 767px) { + +@media (max-width: 767px) { .row-fluid > [class*="span"] + [class*="span"] { - margin-top: 20px + margin-top: 20px; } - .row-fluid input[class*="span"], - .row-fluid textarea[class*="span"], - .row-fluid select[class*="span"] { - width: 80% + .row-fluid input[class*="span"],.row-fluid textarea[class*="span"],.row-fluid select[class*="span"] { + width: 80%; } - .input-prepend, - .input-append { - margin-bottom: 10px + .input-prepend, .input-append { + margin-bottom: 10px; } form .row-fluid > [class*="span"] + [class*="span"] { - margin-top: 0 + margin-top: 0; } .login_page .content_b { - margin: 0 20px + margin: 0 20px; } .search_page .box_view .search_item { - width: 99%; margin-bottom: 3%; + width: 99%; } .error_page .error_box { background: none; width: 100%; } .error_page .error_box h1 { - padding: 40px 20px 0 + padding: 40px 20px 0; } .error_page .error_box p { - margin: 0 20px 10px + margin: 0 20px 10px; } .error_page .error_box .back_link { - margin: 0 20px + margin: 0 20px; } .style_switcher { - display: none + display: none; } .dshb_icoNav { - text-align: center + text-align: center; } .dshb_icoNav li { - float: none; display: inline-block; + float: none; } #cboxContent .video-js { - width: 100% !important; height: 100% !important; + width: 100% !important; } .vcard > .thumbnail { - display: none + display: none; } .vcard > ul { - margin: 0 + margin: 0; } .item-list .thumbnail { - float: none; display: inline-block; + float: none; margin: 0 10px 10px 0; } } -@media (max-width: 479px) { + +@media (max-width: 479px) { .login_page .login_box { - width: 100% + width: 100%; } .login_page .cnt_b { + margin: 0 auto; padding: 20px 0; width: 68%; - margin: 0 auto; } .-list-container { - height: 300px + height: 300px; } } -@media (min-width: 1681px) { + +@media (min-width: 1681px) { body { - max-width: 1680px; margin: 0 auto; + max-width: 1680px; } header .container-fluid { - max-width: 1640px; margin: 0 auto; + max-width: 1640px; } #maincontainer { - border-right: 1px solid #ccc; border-left: 1px solid #ccc; + border-right: 1px solid #ccc; } .main_content { - border-left: none + border-left: none; } .sidebar { left: 50%; margin-left: -839px; } + .sidebar_switch { + left: 50%; + margin-left: -620px; + } + .sidebar_hidden .sidebar_switch { + left: 50%; + margin-left: -832px; + } .sidebar_right .sidebar { - right: 50%; margin-left: 0; margin-right: -840px; + right: 50%; } -} - + .sidebar_right .sidebar_switch { + left: auto; + margin-left: 0; + margin-right: -836px; + right: 50%; + } +} \ No newline at end of file diff --git a/www/themes/profind/css/profind.css b/www/themes/profind/css/profind.css index 9ddaecf..4c98d43 100644 --- a/www/themes/profind/css/profind.css +++ b/www/themes/profind/css/profind.css @@ -354,6 +354,63 @@ a.rowlink { .btn_menu { display: none } + +/* sidebar scroll */ +.antiScroll { + display:inline-block; + position:relative; + overflow:hidden; +} + +.antiscroll-scrollbar { + background:rgba(0,0,0,0.5); + -webkit-border-radius:7px; + -moz-border-radius:7px; + border-radius:7px; + -webkit-box-shadow:0 0 1px #fff; + -moz-box-shadow:0 0 1px #fff; + box-shadow:0 0 1px #fff; + position:absolute; + opacity:0; + filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + -webkit-transition:linear 300ms opacity; + -moz-transition:linear 300ms opacity; + -o-transition:linear 300ms opacity; +} + +.antiscroll-scrollbar-shown { + opacity:1; + filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100); +} + +.antiscroll-scrollbar-horizontal { + height:7px; + margin-left:2px; + bottom:2px; + left:0; +} + +.antiscroll-scrollbar-vertical { + width:7px; + left:2px; + top:0; + margin:2px 0; +} + +.antiscroll-inner { + overflow-y:scroll; +} + +.antiScroll,.antiscroll-content,.antiscroll-inner { + width:240px; +} + +.antiscroll-inner::-webkit-scrollbar,.antiscroll-inner::scrollbar { + width:0; + height:0; +} + + /* main content */ #maincontainer { background-image: url(../images/main_bg.gif); @@ -575,6 +632,11 @@ a.rowlink { .form-horizontal .control-group { margin-bottom: 14px } +.form-horizontal .control-label.error { + color: #B94A48; + font-weight: bold; +} + input.focused { border-color: rgba(82,168,236,.8); -webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); @@ -665,12 +727,17 @@ input[type="text"] + label.error, input[type="password"] + label.error, select + .ui-tooltip label { margin-bottom: 0 } -.f_legend { - font-size: 16px; - line-height: 16px; + +legend { + font-size: 15px; + line-height: 15px; padding-bottom: 10px; - margin-bottom: 22px; - border-bottom: 1px solid #dcdcdc; + margin-bottom: 10px; + border-bottom: 0px; + font-weight: bold; + color: #0088CC; + width: auto; + display: inline; } .radio.inline, .checkbox.inline { margin-left: 0 !important; diff --git a/www/themes/profind/js/profind-general.js b/www/themes/profind/js/profind-general.js new file mode 100644 index 0000000..40be38f --- /dev/null +++ b/www/themes/profind/js/profind-general.js @@ -0,0 +1,257 @@ +//* detect touch devices +function is_touch_device() { + return !!('ontouchstart' in window); +} + +$(document).ready(function() { + + //* accordion change actions + $('#side_accordion').on('hidden shown', function () { + profind_sidebar.make_active(); + profind_sidebar.update_scroll(); + }); + + //* resize elements on window resize + var lastWindowHeight = $(window).height(); + var lastWindowWidth = $(window).width(); + + $(window).on("debouncedresize", function() { + if($(window).height()!=lastWindowHeight || $(window).width()!=lastWindowWidth){ + lastWindowHeight = $(window).height(); + lastWindowWidth = $(window).width(); + profind_sidebar.update_scroll(); + + if(!is_touch_device()){ + $('.sidebar_switch').qtip('hide'); + } + } + }); + //* tooltips + profind_tips.init(); + if(!is_touch_device()){ + //* popovers + profind_popOver.init(); + } + //* sidebar + profind_sidebar.init(); + profind_sidebar.make_active(); + + //* pre block prettify + if(typeof prettyPrint == 'function') { + prettyPrint(); + } + //* external links + profind_external_links.init(); + //* accordion icons + profind_acc_icons.init(); + //* main menu mouseover + profind_nav_mouseover.init(); + //* top submenu + profind_submenu.init(); + + profind_sidebar.make_scroll(); + profind_sidebar.update_scroll(); +}); + +//* external links +profind_external_links = { + init: function() { + $("a[href^='http']").not('.thumbnail>a,.ext_disabled').each(function() { + $(this).attr('target','_blank').addClass('external_link'); + }) + } +}; + +profind_sidebar = { + init: function() { + // sidebar onload state + if($(window).width() > 979){ + if(!$('body').hasClass('sidebar_hidden')) { + if( $.cookie('profind_sidebar') == "hidden") { + $('body').addClass('sidebar_hidden'); + $('.sidebar_switch').toggleClass('on_switch off_switch').attr('title', 'Ver barra'); + } + } else { + $('.sidebar_switch').toggleClass('on_switch off_switch').attr('title', 'Ver barra'); + } + } else { + $('body').addClass('sidebar_hidden'); + $('.sidebar_switch').removeClass('on_switch').addClass('off_switch'); + } + + profind_sidebar.info_box(); + //* sidebar visibility switch + $('.sidebar_switch').click(function(){ + $('.sidebar_switch').removeClass('on_switch off_switch'); + if( $('body').hasClass('sidebar_hidden') ) { + $.cookie('profind_sidebar', null); + $('body').removeClass('sidebar_hidden'); + $('.sidebar_switch').addClass('on_switch').show(); + $('.sidebar_switch').attr( 'title', 'Ocultar barra'); + } else { + $.cookie('profind_sidebar', 'hidden'); + $('body').addClass('sidebar_hidden'); + $('.sidebar_switch').addClass('off_switch'); + $('.sidebar_switch').attr( 'title', 'Ver barra'); + } + profind_sidebar.info_box(); + profind_sidebar.update_scroll(); + $(window).resize(); + }); + //* prevent accordion link click + $('.sidebar .accordion-toggle').click(function(e) { + e.preventDefault() + }); + }, + info_box: function(){ + var s_box = $('.sidebar_info'); + var s_box_height = s_box.actual('height'); + s_box.css({ + 'height' : s_box_height + }); + $('.push').height(s_box_height); + $('.sidebar_inner').css({ + 'margin-bottom' : '-'+s_box_height+'px', + 'min-height' : '100%' + }); + }, + make_active: function() { + var thisAccordion = $('#side_accordion'); + thisAccordion.find('.accordion-heading').removeClass('sdb_h_active'); + var thisHeading = thisAccordion.find('.accordion-body.in').prev('.accordion-heading'); + if(thisHeading.length) { + thisHeading.addClass('sdb_h_active'); + } + }, + make_scroll: function() { + antiScroll = $('.antiScroll').antiscroll().data('antiscroll'); + }, + update_scroll: function() { + if($('.antiScroll').length) { + if( $(window).width() > 979 ){ + $('.antiscroll-inner,.antiscroll-content').height($(window).height() - 40); + } else { + $('.antiscroll-inner,.antiscroll-content').height('400px'); + } + antiScroll.refresh(); + } + } +}; +//* tooltips +profind_tips = { + init: function() { + if(!is_touch_device()){ + var shared = { + style : { + classes: 'ui-tooltip-shadow ui-tooltip-tipsy' + }, + show : { + delay: 100, + event: 'mouseenter focus' + }, + hide : { + delay: 0 + } + }; + if($('.ttip_b').length) { + $('.ttip_b').qtip( $.extend({}, shared, { + position : { + my : 'top center', + at : 'bottom center', + viewport: $(window) + } + })); + } + if($('.ttip_t').length) { + $('.ttip_t').qtip( $.extend({}, shared, { + position: { + my : 'bottom center', + at : 'top center', + viewport: $(window) + } + })); + } + if($('.ttip_l').length) { + $('.ttip_l').qtip( $.extend({}, shared, { + position: { + my : 'right center', + at : 'left center', + viewport: $(window) + } + })); + } + if($('.ttip_r').length) { + $('.ttip_r').qtip( $.extend({}, shared, { + position: { + my : 'left center', + at : 'right center', + viewport: $(window) + } + })); + }; + } + } +}; + +//* popovers +profind_popOver = { + init: function() { + $(".pop_over").popover({ + trigger: 'hover' + }); + } +}; + +//* accordion icons +profind_acc_icons = { + init: function() { + var accordions = $('.main_content .accordion'); + + accordions.find('.accordion-group').each(function(){ + var acc_active = $(this).find('.accordion-body').filter('.in'); + acc_active.prev('.accordion-heading').find('.accordion-toggle').addClass('acc-in'); + }); + accordions.on('show', function(option) { + $(this).find('.accordion-toggle').removeClass('acc-in'); + $(option.target).prev('.accordion-heading').find('.accordion-toggle').addClass('acc-in'); + }); + accordions.on('hide', function(option) { + $(option.target).prev('.accordion-heading').find('.accordion-toggle').removeClass('acc-in'); + }); + } +}; + +//* main menu mouseover +profind_nav_mouseover = { + init: function() { + $('header li.dropdown').mouseenter(function() { + if($('body').hasClass('menu_hover')) { + $(this).addClass('navHover') + } + }).mouseleave(function() { + if($('body').hasClass('menu_hover')) { + $(this).removeClass('navHover open') + } + }); + } +}; + +//* submenu +profind_submenu = { + init: function() { + $('.dropdown-menu li').each(function(){ + var $this = $(this); + if($this.children('ul').length) { + $this.addClass('sub-dropdown'); + $this.children('ul').addClass('sub-menu'); + } + }); + + $('.sub-dropdown').on('mouseenter',function(){ + $(this).addClass('active').children('ul').addClass('sub-open'); + }).on('mouseleave', function() { + $(this).removeClass('active').children('ul').removeClass('sub-open'); + }) + + } +}; \ No newline at end of file diff --git a/www/themes/profind/lib/actual/.gitignore b/www/themes/profind/lib/actual/.gitignore new file mode 100644 index 0000000..5ca0973 --- /dev/null +++ b/www/themes/profind/lib/actual/.gitignore @@ -0,0 +1,2 @@ +.DS_Store + diff --git a/www/themes/profind/lib/actual/CHANGELOG.md b/www/themes/profind/lib/actual/CHANGELOG.md new file mode 100644 index 0000000..7de2c98 --- /dev/null +++ b/www/themes/profind/lib/actual/CHANGELOG.md @@ -0,0 +1,65 @@ +# jQuery Actual Plugin CHANGELOG + +## 1.0.10 + +- [bug fix] Override `!imporant` css declarations + + + +## 1.0.9 + +- [bug fix] jQuery 1.8.0 compatibility + + + +## 1.0.8 + +- [bug fix] Inverted code lines + + + +## 1.0.7 + +- [refactoring] Save/restore element style rather than individual CSS attributes( thanks to Jon Tara ) + + + +## 1.0.6 + +- [bug fixed] Pass `configs.includeMargin` to only `outerWidth` and `outerHeight` so it does not break in $ 1.7.2 + + + +## 1.0.5 + +- Add package.json for new jquery plugin site + + + +## 1.0.4 + +- Add `includeMargin` for `outerWidth`( thanks to Erwin Derksen ) + + + +## 1.0.3 + +- [bug fixed] `$` namespace conflict + + + +## 1.0.2 + +- [bug fixed] Typo + + + +## 1.0.1 + +- [bug fixed] Typo + + + +## 1.0.0 + +- First stable release diff --git a/www/themes/profind/lib/actual/LICENSE.txt b/www/themes/profind/lib/actual/LICENSE.txt new file mode 100644 index 0000000..a07c70a --- /dev/null +++ b/www/themes/profind/lib/actual/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2011, Ben Lin (http://dreamerslab.com/) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/www/themes/profind/lib/actual/README.md b/www/themes/profind/lib/actual/README.md new file mode 100644 index 0000000..c0edd08 --- /dev/null +++ b/www/themes/profind/lib/actual/README.md @@ -0,0 +1,107 @@ +# jQuery Actual Plugin + +Get the actual width/height of invisible DOM elements with jQuery. + + + +## Description + +jQuery has trouble finding the width/height of invisible DOM elements. With element or its parent element has css property 'display' set to 'none'. `$('.hidden').width();` will return 0 instead of the actual width; This plugin simply fix it. + + + +## Demo + +- Normal usage see demo/normal.html +- If you use [css3pie](http://css3pie.com/) you might also want to take a look at another demo( demo/css3pie.html ) +- Live demo please take a look at [this](http://dreamerslab.com/demos/get-hidden-element-width-with-jquery-actual-plugin) and [this](http://dreamerslab.com/demos/get-hidden-element-width-with-jquery-actual-plugin-with-css3pie/) + + + +## Documentation + +- There is a syntax highlight version, please see [this post](http://dreamerslab.com/blog/en/get-hidden-elements-width-and-height-with-jquery/) +- For chinese version please go [here](http://dreamerslab.com/blog/tw/get-hidden-elements-width-and-height-with-jquery/) + + + +## Requires + +- jQuery 1.2.3 ~ 1.8.0 + + + +## Browser Compatibility + +- [Firefox](http://mzl.la/RNaI) 2.0+ +- [Internet Explorer](http://bit.ly/9fMgIQ) 6+ +- [Safari](http://bit.ly/gMhzVR) 3+ +- [Opera](http://bit.ly/fWJzaC) 10.6+ +- [Chrome](http://bit.ly/ePHvYZ) 8+ + + + +## Installation +- First, make sure you are using valid [DOCTYPE](http://bit.ly/hQK1Rk) +- Include necessary JS files + + + + + + + + +## Usage + +Example code: + + // get hidden element actual width + $( '.hidden' ).actual( 'width' ); + + // get hidden element actual innerWidth + $( '.hidden' ).actual( 'innerWidth' ); + + // get hidden element actual outerWidth + $( '.hidden' ).actual( 'outerWidth' ); + + // get hidden element actual outerWidth and set the `includeMargin` argument + $( '.hidden' ).actual( 'outerWidth', { includeMargin : true }); + + // get hidden element actual height + $( '.hidden' ).actual( 'height' ); + + // get hidden element actual innerHeight + $( '.hidden' ).actual( 'innerHeight' ); + + // get hidden element actual outerHeight + $( '.hidden' ).actual( 'outerHeight' ); + + // get hidden element actual outerHeight and set the `includeMargin` argument + $( '.hidden' ).actual( 'outerHeight', { includeMargin : true }); + + // if the page jumps or blinks, pass a attribute '{ absolute : true }' + // be very careful, you might get a wrong result depends on how you makrup your html and css + $( '.hidden' ).actual( 'height', { absolute : true }); + + // if you use css3pie with a float element + // for example a rounded corner navigation menu you can also try to pass a attribute '{ clone : true }' + // please see demo/css3pie in action + $( '.hidden' ).actual( 'width', { clone : true }); + + + +## Credits + +- Erwin Derksen +- [Jon Tara](https://github.com/jtara) +- [Matt Hinchliffe](https://github.com/i-like-robots) +- [Ryan Millikin](https://github.com/dhamma) + + + +## License + +The expandable plugin is licensed under the MIT License (LICENSE.txt). + +Copyright (c) 2012 [Ben Lin](http://dreamerslab.com) \ No newline at end of file diff --git a/www/themes/profind/lib/actual/jquery.actual.js b/www/themes/profind/lib/actual/jquery.actual.js new file mode 100644 index 0000000..764a41a --- /dev/null +++ b/www/themes/profind/lib/actual/jquery.actual.js @@ -0,0 +1,97 @@ +/*! Copyright 2012, Ben Lin (http://dreamerslab.com/) +* Licensed under the MIT License (LICENSE.txt). +* +* Version: 1.0.10 +* +* Requires: jQuery 1.2.3 ~ 1.8.0 +*/ +;( function ( $ ){ + $.fn.extend({ + actual : function ( method, options ){ + // check if the jQuery method exist + if( !this[ method ]){ + throw '$.actual => The jQuery method "' + method + '" you called does not exist'; + } + + var defaults = { + absolute : false, + clone : false, + includeMargin : false + }; + + var configs = $.extend( defaults, options ); + + var $target = this; + var fix, restore; + + if( configs.clone === true ){ + fix = function (){ + var style = 'position: absolute !important; top: -1000 !important; '; + + // this is useful with css3pie + $target = $target. + filter( ':first' ). + clone(). + attr( 'style', style ). + appendTo( 'body' ); + }; + + restore = function (){ + // remove DOM element after getting the width + $target.remove(); + }; + }else{ + var tmp = []; + var $hidden, style; + + fix = function (){ + // get all hidden parents + $hidden = $target. + parents(). + andSelf(). + filter( ':hidden' ); + + style += 'visibility: hidden !important; display: block !important; '; + + if( configs.absolute === true ) style += 'position: absolute !important; '; + + // save the origin style props + // set the hidden el css to be got the actual value later + $hidden.each( function (){ + var $this = $( this ); + + // Save original style. If no style was set, attr() returns undefined + tmp.push( $this.attr( 'style' )); + $this.attr( 'style', style ); + }); + }; + + restore = function (){ + // restore origin style values + $hidden.each( function ( i ){ + var $this = $( this ); + var _tmp = tmp[ i ]; + + if( _tmp === undefined ){ + $this.removeAttr( 'style' ); + }else{ + $this.attr( 'style', _tmp ); + } + }); + }; + } + + fix(); + // get the actual value with user specific methed + // it can be 'width', 'height', 'outerWidth', 'innerWidth'... etc + // configs.includeMargin only works for 'outerWidth' and 'outerHeight' + var actual = /(outer)/g.test( method ) ? + $target[ method ]( configs.includeMargin ) : + $target[ method ](); + + restore(); + // IMPORTANT, this plugin only return the value of the first element + return actual; + } + }); +})( jQuery ); \ No newline at end of file diff --git a/www/themes/profind/lib/actual/jquery.actual.min.js b/www/themes/profind/lib/actual/jquery.actual.min.js new file mode 100644 index 0000000..2a9f0ea --- /dev/null +++ b/www/themes/profind/lib/actual/jquery.actual.min.js @@ -0,0 +1,8 @@ +/*! Copyright 2012, Ben Lin (http://dreamerslab.com/) +* Licensed under the MIT License (LICENSE.txt). +* +* Version: 1.0.10 +* +* Requires: jQuery 1.2.3 ~ 1.8.0 +*/ +;(function(a){a.fn.extend({actual:function(b,l){if(!this[b]){throw'$.actual => The jQuery method "'+b+'" you called does not exist';}var f={absolute:false,clone:false,includeMargin:false};var i=a.extend(f,l);var e=this;var h,j;if(i.clone===true){h=function(){var m="position: absolute !important; top: -1000 !important; ";e=e.filter(":first").clone().attr("style",m).appendTo("body");};j=function(){e.remove();};}else{var g=[];var d,c;h=function(){d=e.parents().andSelf().filter(":hidden");c+="visibility: hidden !important; display: block !important; ";if(i.absolute===true){c+="position: absolute !important; ";}d.each(function(){var m=a(this);g.push(m.attr("style"));m.attr("style",c);});};j=function(){d.each(function(m){var o=a(this);var n=g[m];if(n===undefined){o.removeAttr("style");}else{o.attr("style",n);}});};}h();var k=/(outer)/g.test(b)?e[b](i.includeMargin):e[b]();j();return k;}});})(jQuery); \ No newline at end of file diff --git a/www/themes/profind/lib/actual/package.json b/www/themes/profind/lib/actual/package.json new file mode 100644 index 0000000..53cb9b1 --- /dev/null +++ b/www/themes/profind/lib/actual/package.json @@ -0,0 +1,25 @@ +{ + "name" : "actual", + "version" : "1.0.10", + "title" : "jQuery Actual Plugin", + "author" : "dreamerslab ", + "description": "Older version of jQuery has trouble finding the width/height of invisible DOM elements. With element or its parent element has css property 'display' set to 'none'. `$('.hidden').width();` will return 0 instead of the actual width; This plugin simply fix it.", + "keywords": [ + "width", "height", "hidden element width", "hidden element height", "actual" + ], + "dependencies": { + "jquery": ">=1.2.3" + }, + "contributors": [ + { "name": "Ben Lin", "email": "ben@dreamerslab.com" }, + { "name": "Erwin Derksen" }, + { "name": "Jon Tara", "email": "jtara-github-public@spamex.com" }, + { "name": "Matt Hinchliffe", "email": "matt@maketea.co.uk" }, + { "name": "Ryan Millikin" } + ], + "licenses": [{ + "type" : "MIT", + "url" : "LICENSE.txt" + }], + "homepage": "http://dreamerslab.com/blog/get-hidden-elements-width-and-height-with-jquery/" +} \ No newline at end of file diff --git a/www/themes/profind/lib/antiscroll/antiscroll.css b/www/themes/profind/lib/antiscroll/antiscroll.css new file mode 100644 index 0000000..f30a449 --- /dev/null +++ b/www/themes/profind/lib/antiscroll/antiscroll.css @@ -0,0 +1,54 @@ +.antiScroll { + display: inline-block; + position: relative; + overflow: hidden; +} + +.antiscroll-scrollbar { + background: gray; + background: rgba(0, 0, 0, 0.5); + -webkit-border-radius: 7px; + -moz-border-radius: 7px; + border-radius: 7px; + -webkit-box-shadow: 0 0 1px #fff; + -moz-box-shadow: 0 0 1px #fff; + box-shadow: 0 0 1px #fff; + position: absolute; + opacity: 0; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + -webkit-transition: linear 300ms opacity; + -moz-transition: linear 300ms opacity; + -o-transition: linear 300ms opacity; +} + +.antiscroll-scrollbar-shown { + opacity: 1; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); +} + +.antiscroll-scrollbar-horizontal { + height: 7px; + margin-left: 2px; + bottom: 2px; + left: 0; +} + +.antiscroll-scrollbar-vertical { + width: 7px; + margin-top: 2px; + right: 2px; + top: 0; +} + +.antiscroll-inner { + overflow-y: scroll; +} + +.antiScroll,.antiscroll-content, .antiscroll-inner { + width: 240px; +} + +.antiscroll-inner::-webkit-scrollbar, .antiscroll-inner::scrollbar { + width: 0; + height: 0; +} diff --git a/www/themes/profind/lib/antiscroll/antiscroll.js b/www/themes/profind/lib/antiscroll/antiscroll.js new file mode 100644 index 0000000..ca75bcc --- /dev/null +++ b/www/themes/profind/lib/antiscroll/antiscroll.js @@ -0,0 +1,446 @@ + +(function ($) { + + /** + * Augment jQuery prototype. + */ + + $.fn.antiscroll = function (options) { + return this.each(function () { + if ($(this).data('antiscroll')) { + $(this).data('antiscroll').destroy(); + } + + $(this).data('antiscroll', new $.Antiscroll(this, options)); + }); + }; + + /** + * Expose constructor. + */ + + $.Antiscroll = Antiscroll; + + /** + * Antiscroll pane constructor. + * + * @param {Element|jQuery} main pane + * @parma {Object} options + * @api public + */ + + function Antiscroll (el, opts) { + this.el = $(el); + this.options = opts || {}; + + this.x = false !== this.options.x; + this.y = false !== this.options.y; + this.padding = undefined == this.options.padding ? 2 : this.options.padding; + + this.inner = this.el.find('.antiscroll-inner'); + this.inner.css({ + 'width': '+=' + scrollbarSize() + , 'height': '+=' + scrollbarSize() + }); + + this.refresh(); + } + + /** + * refresh scrollbars + * + * @api public + */ + + Antiscroll.prototype.refresh = function() { + var needHScroll = this.inner.get(0).scrollWidth > this.el.width() + , needVScroll = this.inner.get(0).scrollHeight > this.el.height(); + + if (!this.horizontal && needHScroll && this.x) { + this.horizontal = new Scrollbar.Horizontal(this); + } else if (this.horizontal && !needHScroll) { + this.horizontal.destroy(); + this.horizontal = null + } + + if (!this.vertical && needVScroll && this.y) { + this.vertical = new Scrollbar.Vertical(this); + } else if (this.vertical && !needVScroll) { + this.vertical.destroy(); + this.vertical = null + } + }; + + /** + * Cleans up. + * + * @return {Antiscroll} for chaining + * @api public + */ + + Antiscroll.prototype.destroy = function () { + if (this.horizontal) { + this.horizontal.destroy(); + this.horizontal = null + } + if (this.vertical) { + this.vertical.destroy(); + } + return this; + }; + + /** + * Rebuild Antiscroll. + * + * @return {Antiscroll} for chaining + * @api public + */ + + Antiscroll.prototype.rebuild = function () { + this.destroy(); + this.inner.attr('style', ''); + Antiscroll.call(this, this.el, this.options); + return this; + }; + + /** + * Scrollbar constructor. + * + * @param {Element|jQuery} element + * @api public + */ + + function Scrollbar (pane) { + this.pane = pane; + this.pane.el.append(this.el); + this.innerEl = this.pane.inner.get(0); + + this.dragging = false; + this.enter = false; + this.shown = false; + + // hovering + this.pane.el.mouseenter($.proxy(this, 'mouseenter')); + this.pane.el.mouseleave($.proxy(this, 'mouseleave')); + + // dragging + this.el.mousedown($.proxy(this, 'mousedown')); + + // scrolling + this.innerPaneScrollListener = $.proxy(this, 'scroll'); + this.pane.inner.scroll(this.innerPaneScrollListener); + + // wheel -optional- + this.innerPaneMouseWheelListener = $.proxy(this, 'mousewheel'); + this.pane.inner.bind('mousewheel', this.innerPaneMouseWheelListener); + + // show + var initialDisplay = this.pane.options.initialDisplay; + + if (initialDisplay !== false) { + this.show(); + this.hiding = setTimeout($.proxy(this, 'hide'), parseInt(initialDisplay, 10) || 3000); + } + } + + /** + * Cleans up. + * + * @return {Scrollbar} for chaining + * @api public + */ + + Scrollbar.prototype.destroy = function () { + this.el.remove(); + this.pane.inner.unbind('scroll', this.innerPaneScrollListener); + this.pane.inner.unbind('mousewheel', this.innerPaneMouseWheelListener); + return this; + }; + + /** + * Called upon mouseenter. + * + * @api private + */ + + Scrollbar.prototype.mouseenter = function () { + this.enter = true; + this.show(); + }; + + /** + * Called upon mouseleave. + * + * @api private + */ + + Scrollbar.prototype.mouseleave = function () { + this.enter = false; + + if (!this.dragging) { + this.hide(); + } + } + + /** + * Called upon wrap scroll. + * + * @api private + */ + + Scrollbar.prototype.scroll = function () { + if (!this.shown) { + this.show(); + if (!this.enter && !this.dragging) { + this.hiding = setTimeout($.proxy(this, 'hide'), 1500); + } + } + + this.update(); + }; + + /** + * Called upon scrollbar mousedown. + * + * @api private + */ + + Scrollbar.prototype.mousedown = function (ev) { + ev.preventDefault(); + + this.dragging = true; + + this.startPageY = ev.pageY - parseInt(this.el.css('top'), 10); + this.startPageX = ev.pageX - parseInt(this.el.css('left'), 10); + + // prevent crazy selections on IE + document.onselectstart = function () { return false; }; + + var pane = this.pane + , move = $.proxy(this, 'mousemove') + , self = this + + $(document) + .mousemove(move) + .mouseup(function () { + self.dragging = false; + document.onselectstart = null; + + $(document).unbind('mousemove', move); + + if (!self.enter) { + self.hide(); + } + }) + }; + + /** + * Show scrollbar. + * + * @api private + */ + + Scrollbar.prototype.show = function (duration) { + if (!this.shown) { + this.update(); + this.el.addClass('antiscroll-scrollbar-shown'); + if (this.hiding) { + clearTimeout(this.hiding); + this.hiding = null; + } + this.shown = true; + } + }; + + /** + * Hide scrollbar. + * + * @api private + */ + + Scrollbar.prototype.hide = function () { + var autoHide = this.pane.options.autoHide; + if (autoHide !== false && this.shown) { + // check for dragging + this.el.removeClass('antiscroll-scrollbar-shown'); + this.shown = false; + } + }; + + /** + * Horizontal scrollbar constructor + * + * @api private + */ + + Scrollbar.Horizontal = function (pane) { + this.el = $('
'); + Scrollbar.call(this, pane); + } + + /** + * Inherits from Scrollbar. + */ + + inherits(Scrollbar.Horizontal, Scrollbar); + + /** + * Updates size/position of scrollbar. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.update = function () { + var paneWidth = this.pane.el.width() + , trackWidth = paneWidth - this.pane.padding * 2 + , innerEl = this.pane.inner.get(0) + + this.el + .css('width', trackWidth * paneWidth / innerEl.scrollWidth) + .css('left', trackWidth * innerEl.scrollLeft / innerEl.scrollWidth) + } + + /** + * Called upon drag. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.mousemove = function (ev) { + var trackWidth = this.pane.el.width() - this.pane.padding * 2 + , pos = ev.pageX - this.startPageX + , barWidth = this.el.width() + , innerEl = this.pane.inner.get(0) + + // minimum top is 0, maximum is the track height + var y = Math.min(Math.max(pos, 0), trackWidth - barWidth) + + innerEl.scrollLeft = (innerEl.scrollWidth - this.pane.el.width()) + * y / (trackWidth - barWidth) + }; + + /** + * Called upon container mousewheel. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.mousewheel = function (ev, delta, x, y) { + if ((x < 0 && 0 == this.pane.inner.get(0).scrollLeft) || + (x > 0 && (this.innerEl.scrollLeft + this.pane.el.width() + == this.innerEl.scrollWidth))) { + ev.preventDefault(); + return false; + } + }; + + /** + * Vertical scrollbar constructor + * + * @api private + */ + + Scrollbar.Vertical = function (pane) { + this.el = $('
'); + Scrollbar.call(this, pane); + }; + + /** + * Inherits from Scrollbar. + */ + + inherits(Scrollbar.Vertical, Scrollbar); + + /** + * Updates size/position of scrollbar. + * + * @api private + */ + + Scrollbar.Vertical.prototype.update = function () { + var paneHeight = this.pane.el.height() + , trackHeight = paneHeight - this.pane.padding * 2 + , innerEl = this.innerEl + + this.el + .css('height', trackHeight * paneHeight / innerEl.scrollHeight) + .css('top', trackHeight * innerEl.scrollTop / innerEl.scrollHeight) + }; + + /** + * Called upon drag. + * + * @api private + */ + + Scrollbar.Vertical.prototype.mousemove = function (ev) { + var paneHeight = this.pane.el.height() + , trackHeight = paneHeight - this.pane.padding * 2 + , pos = ev.pageY - this.startPageY + , barHeight = this.el.height() + , innerEl = this.innerEl + + // minimum top is 0, maximum is the track height + var y = Math.min(Math.max(pos, 0), trackHeight - barHeight) + + innerEl.scrollTop = (innerEl.scrollHeight - paneHeight) + * y / (trackHeight - barHeight) + }; + + /** + * Called upon container mousewheel. + * + * @api private + */ + + Scrollbar.Vertical.prototype.mousewheel = function (ev, delta, x, y) { + if ((y > 0 && 0 == this.innerEl.scrollTop) || + (y < 0 && (this.innerEl.scrollTop + this.pane.el.height() + == this.innerEl.scrollHeight))) { + ev.preventDefault(); + return false; + } + }; + + /** + * Cross-browser inheritance. + * + * @param {Function} constructor + * @param {Function} constructor we inherit from + * @api private + */ + + function inherits (ctorA, ctorB) { + function f() {}; + f.prototype = ctorB.prototype; + ctorA.prototype = new f; + }; + + /** + * Scrollbar size detection. + */ + + var size; + + function scrollbarSize () { + if (size === undefined) { + var div = $( + '
' + + '
' + ); + + $('body').append(div); + + var w1 = $('div', div).innerWidth(); + div.css('overflow-y', 'scroll'); + var w2 = $('div', div).innerWidth(); + $(div).remove(); + + size = w1 - w2; + } + + return size; + }; + +})(jQuery); diff --git a/www/themes/profind/lib/antiscroll/antiscroll.min.js b/www/themes/profind/lib/antiscroll/antiscroll.min.js new file mode 100644 index 0000000..ca75bcc --- /dev/null +++ b/www/themes/profind/lib/antiscroll/antiscroll.min.js @@ -0,0 +1,446 @@ + +(function ($) { + + /** + * Augment jQuery prototype. + */ + + $.fn.antiscroll = function (options) { + return this.each(function () { + if ($(this).data('antiscroll')) { + $(this).data('antiscroll').destroy(); + } + + $(this).data('antiscroll', new $.Antiscroll(this, options)); + }); + }; + + /** + * Expose constructor. + */ + + $.Antiscroll = Antiscroll; + + /** + * Antiscroll pane constructor. + * + * @param {Element|jQuery} main pane + * @parma {Object} options + * @api public + */ + + function Antiscroll (el, opts) { + this.el = $(el); + this.options = opts || {}; + + this.x = false !== this.options.x; + this.y = false !== this.options.y; + this.padding = undefined == this.options.padding ? 2 : this.options.padding; + + this.inner = this.el.find('.antiscroll-inner'); + this.inner.css({ + 'width': '+=' + scrollbarSize() + , 'height': '+=' + scrollbarSize() + }); + + this.refresh(); + } + + /** + * refresh scrollbars + * + * @api public + */ + + Antiscroll.prototype.refresh = function() { + var needHScroll = this.inner.get(0).scrollWidth > this.el.width() + , needVScroll = this.inner.get(0).scrollHeight > this.el.height(); + + if (!this.horizontal && needHScroll && this.x) { + this.horizontal = new Scrollbar.Horizontal(this); + } else if (this.horizontal && !needHScroll) { + this.horizontal.destroy(); + this.horizontal = null + } + + if (!this.vertical && needVScroll && this.y) { + this.vertical = new Scrollbar.Vertical(this); + } else if (this.vertical && !needVScroll) { + this.vertical.destroy(); + this.vertical = null + } + }; + + /** + * Cleans up. + * + * @return {Antiscroll} for chaining + * @api public + */ + + Antiscroll.prototype.destroy = function () { + if (this.horizontal) { + this.horizontal.destroy(); + this.horizontal = null + } + if (this.vertical) { + this.vertical.destroy(); + } + return this; + }; + + /** + * Rebuild Antiscroll. + * + * @return {Antiscroll} for chaining + * @api public + */ + + Antiscroll.prototype.rebuild = function () { + this.destroy(); + this.inner.attr('style', ''); + Antiscroll.call(this, this.el, this.options); + return this; + }; + + /** + * Scrollbar constructor. + * + * @param {Element|jQuery} element + * @api public + */ + + function Scrollbar (pane) { + this.pane = pane; + this.pane.el.append(this.el); + this.innerEl = this.pane.inner.get(0); + + this.dragging = false; + this.enter = false; + this.shown = false; + + // hovering + this.pane.el.mouseenter($.proxy(this, 'mouseenter')); + this.pane.el.mouseleave($.proxy(this, 'mouseleave')); + + // dragging + this.el.mousedown($.proxy(this, 'mousedown')); + + // scrolling + this.innerPaneScrollListener = $.proxy(this, 'scroll'); + this.pane.inner.scroll(this.innerPaneScrollListener); + + // wheel -optional- + this.innerPaneMouseWheelListener = $.proxy(this, 'mousewheel'); + this.pane.inner.bind('mousewheel', this.innerPaneMouseWheelListener); + + // show + var initialDisplay = this.pane.options.initialDisplay; + + if (initialDisplay !== false) { + this.show(); + this.hiding = setTimeout($.proxy(this, 'hide'), parseInt(initialDisplay, 10) || 3000); + } + } + + /** + * Cleans up. + * + * @return {Scrollbar} for chaining + * @api public + */ + + Scrollbar.prototype.destroy = function () { + this.el.remove(); + this.pane.inner.unbind('scroll', this.innerPaneScrollListener); + this.pane.inner.unbind('mousewheel', this.innerPaneMouseWheelListener); + return this; + }; + + /** + * Called upon mouseenter. + * + * @api private + */ + + Scrollbar.prototype.mouseenter = function () { + this.enter = true; + this.show(); + }; + + /** + * Called upon mouseleave. + * + * @api private + */ + + Scrollbar.prototype.mouseleave = function () { + this.enter = false; + + if (!this.dragging) { + this.hide(); + } + } + + /** + * Called upon wrap scroll. + * + * @api private + */ + + Scrollbar.prototype.scroll = function () { + if (!this.shown) { + this.show(); + if (!this.enter && !this.dragging) { + this.hiding = setTimeout($.proxy(this, 'hide'), 1500); + } + } + + this.update(); + }; + + /** + * Called upon scrollbar mousedown. + * + * @api private + */ + + Scrollbar.prototype.mousedown = function (ev) { + ev.preventDefault(); + + this.dragging = true; + + this.startPageY = ev.pageY - parseInt(this.el.css('top'), 10); + this.startPageX = ev.pageX - parseInt(this.el.css('left'), 10); + + // prevent crazy selections on IE + document.onselectstart = function () { return false; }; + + var pane = this.pane + , move = $.proxy(this, 'mousemove') + , self = this + + $(document) + .mousemove(move) + .mouseup(function () { + self.dragging = false; + document.onselectstart = null; + + $(document).unbind('mousemove', move); + + if (!self.enter) { + self.hide(); + } + }) + }; + + /** + * Show scrollbar. + * + * @api private + */ + + Scrollbar.prototype.show = function (duration) { + if (!this.shown) { + this.update(); + this.el.addClass('antiscroll-scrollbar-shown'); + if (this.hiding) { + clearTimeout(this.hiding); + this.hiding = null; + } + this.shown = true; + } + }; + + /** + * Hide scrollbar. + * + * @api private + */ + + Scrollbar.prototype.hide = function () { + var autoHide = this.pane.options.autoHide; + if (autoHide !== false && this.shown) { + // check for dragging + this.el.removeClass('antiscroll-scrollbar-shown'); + this.shown = false; + } + }; + + /** + * Horizontal scrollbar constructor + * + * @api private + */ + + Scrollbar.Horizontal = function (pane) { + this.el = $('
'); + Scrollbar.call(this, pane); + } + + /** + * Inherits from Scrollbar. + */ + + inherits(Scrollbar.Horizontal, Scrollbar); + + /** + * Updates size/position of scrollbar. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.update = function () { + var paneWidth = this.pane.el.width() + , trackWidth = paneWidth - this.pane.padding * 2 + , innerEl = this.pane.inner.get(0) + + this.el + .css('width', trackWidth * paneWidth / innerEl.scrollWidth) + .css('left', trackWidth * innerEl.scrollLeft / innerEl.scrollWidth) + } + + /** + * Called upon drag. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.mousemove = function (ev) { + var trackWidth = this.pane.el.width() - this.pane.padding * 2 + , pos = ev.pageX - this.startPageX + , barWidth = this.el.width() + , innerEl = this.pane.inner.get(0) + + // minimum top is 0, maximum is the track height + var y = Math.min(Math.max(pos, 0), trackWidth - barWidth) + + innerEl.scrollLeft = (innerEl.scrollWidth - this.pane.el.width()) + * y / (trackWidth - barWidth) + }; + + /** + * Called upon container mousewheel. + * + * @api private + */ + + Scrollbar.Horizontal.prototype.mousewheel = function (ev, delta, x, y) { + if ((x < 0 && 0 == this.pane.inner.get(0).scrollLeft) || + (x > 0 && (this.innerEl.scrollLeft + this.pane.el.width() + == this.innerEl.scrollWidth))) { + ev.preventDefault(); + return false; + } + }; + + /** + * Vertical scrollbar constructor + * + * @api private + */ + + Scrollbar.Vertical = function (pane) { + this.el = $('
'); + Scrollbar.call(this, pane); + }; + + /** + * Inherits from Scrollbar. + */ + + inherits(Scrollbar.Vertical, Scrollbar); + + /** + * Updates size/position of scrollbar. + * + * @api private + */ + + Scrollbar.Vertical.prototype.update = function () { + var paneHeight = this.pane.el.height() + , trackHeight = paneHeight - this.pane.padding * 2 + , innerEl = this.innerEl + + this.el + .css('height', trackHeight * paneHeight / innerEl.scrollHeight) + .css('top', trackHeight * innerEl.scrollTop / innerEl.scrollHeight) + }; + + /** + * Called upon drag. + * + * @api private + */ + + Scrollbar.Vertical.prototype.mousemove = function (ev) { + var paneHeight = this.pane.el.height() + , trackHeight = paneHeight - this.pane.padding * 2 + , pos = ev.pageY - this.startPageY + , barHeight = this.el.height() + , innerEl = this.innerEl + + // minimum top is 0, maximum is the track height + var y = Math.min(Math.max(pos, 0), trackHeight - barHeight) + + innerEl.scrollTop = (innerEl.scrollHeight - paneHeight) + * y / (trackHeight - barHeight) + }; + + /** + * Called upon container mousewheel. + * + * @api private + */ + + Scrollbar.Vertical.prototype.mousewheel = function (ev, delta, x, y) { + if ((y > 0 && 0 == this.innerEl.scrollTop) || + (y < 0 && (this.innerEl.scrollTop + this.pane.el.height() + == this.innerEl.scrollHeight))) { + ev.preventDefault(); + return false; + } + }; + + /** + * Cross-browser inheritance. + * + * @param {Function} constructor + * @param {Function} constructor we inherit from + * @api private + */ + + function inherits (ctorA, ctorB) { + function f() {}; + f.prototype = ctorB.prototype; + ctorA.prototype = new f; + }; + + /** + * Scrollbar size detection. + */ + + var size; + + function scrollbarSize () { + if (size === undefined) { + var div = $( + '
' + + '
' + ); + + $('body').append(div); + + var w1 = $('div', div).innerWidth(); + div.css('overflow-y', 'scroll'); + var w2 = $('div', div).innerWidth(); + $(div).remove(); + + size = w1 - w2; + } + + return size; + }; + +})(jQuery); diff --git a/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js b/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js new file mode 100644 index 0000000..dbf8f4b --- /dev/null +++ b/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js @@ -0,0 +1,78 @@ +/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) + * Licensed under the MIT License (LICENSE.txt). + * + * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. + * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. + * Thanks to: Seamus Leahy for adding deltaX and deltaY + * + * Version: 3.0.4 + * + * Requires: 1.2.2+ + */ + +(function($) { + +var types = ['DOMMouseScroll', 'mousewheel']; + +$.event.special.mousewheel = { + setup: function() { + if ( this.addEventListener ) { + for ( var i=types.length; i; ) { + this.addEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = handler; + } + }, + + teardown: function() { + if ( this.removeEventListener ) { + for ( var i=types.length; i; ) { + this.removeEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = null; + } + } +}; + +$.fn.extend({ + mousewheel: function(fn) { + return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); + }, + + unmousewheel: function(fn) { + return this.unbind("mousewheel", fn); + } +}); + + +function handler(event) { + var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; + event = $.event.fix(orgEvent); + event.type = "mousewheel"; + + // Old school scrollwheel delta + if ( event.wheelDelta ) { delta = event.wheelDelta/120; } + if ( event.detail ) { delta = -event.detail/3; } + + // New school multidimensional scroll (touchpads) deltas + deltaY = delta; + + // Gecko + if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { + deltaY = 0; + deltaX = -1*delta; + } + + // Webkit + if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } + if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } + + // Add event and delta to the front of the arguments + args.unshift(event, delta, deltaX, deltaY); + + return $.event.handle.apply(this, args); +} + +})(jQuery); \ No newline at end of file diff --git a/www/themes/profind/lib/antiscroll/index.html b/www/themes/profind/lib/antiscroll/index.html new file mode 100644 index 0000000..0596ee1 --- /dev/null +++ b/www/themes/profind/lib/antiscroll/index.html @@ -0,0 +1,304 @@ + + + + Antiscroll - os x lion style cross-browser native scrolling on the web that gets out of the way + + + + + + + + + + + +
+

Antiscroll

+

os x lion style cross-browser native scrolling on the web that gets out of the way.

+
    +
  • supports mousewheels, trackpads, other input devices natively.
  • +
  • total size is 1kb minified and gzipped.
  • +
  • doesn't magically autowrap your elements with divs (manual wrapping is necessary, please see index.html demo).
  • +
  • fade in/out controlled with CSS3 animations.
  • +
  • shows scrollbars upon hovering.
  • +
  • scrollbars are draggable.
  • +
  • size of container can be dynamically adjusted and scrollbars will adapt.
  • +
  • supports IE7+, Firefox 3+, Chrome, Safari, Opera
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
BodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBodyBody
+
+
+
+
+
+
Download + +
+ +

X rows

+ + +

X cols

+ +
  • Add col
  • +
  • Remove col
  • + + +
    + + diff --git a/www/themes/profind/lib/cookie/CHANGELOG.md b/www/themes/profind/lib/cookie/CHANGELOG.md new file mode 100644 index 0000000..e47d325 --- /dev/null +++ b/www/themes/profind/lib/cookie/CHANGELOG.md @@ -0,0 +1,17 @@ +1.3 (wip) +--- +- Configuration options: `raw`, `json`. Replaces raw option, becomes config: + +```javascript +$.cookie.raw = true; // bypass encoding/decoding the cookie value +$.cookie.json = true; // automatically JSON stringify/parse value +``` +Thus the default options now cleanly contain cookie attributes only. + +1.2 +--- +- Adding `$.removeCookie('foo')` for deleting a cookie, using `$.cookie('foo', null)` is now deprecated. + +1.1 +--- +- Default options. diff --git a/www/themes/profind/lib/cookie/README.md b/www/themes/profind/lib/cookie/README.md new file mode 100644 index 0000000..301e356 --- /dev/null +++ b/www/themes/profind/lib/cookie/README.md @@ -0,0 +1,92 @@ +# jquery.cookie + +A simple, lightweight jQuery plugin for reading, writing and deleting cookies. + +## Installation + +Include script *after* the jQuery library (unless you are packaging scripts somehow else): + + + +**Do not include the script directly from GitHub (http://raw.github.com/...).** The file is being served as text/plain and as such being blocked +in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN. + +## Usage + +Create session cookie: + + $.cookie('the_cookie', 'the_value'); + +Create expiring cookie, 7 days from then: + + $.cookie('the_cookie', 'the_value', { expires: 7 }); + +Create expiring cookie, valid across entire site: + + $.cookie('the_cookie', 'the_value', { expires: 7, path: '/' }); + +Read cookie: + + $.cookie('the_cookie'); // => "the_value" + $.cookie('not_existing'); // => null + +Delete cookie: + + // Returns true when cookie was found, false when no cookie was found... + $.removeCookie('the_cookie'); + + // Same path as when the cookie was written... + $.removeCookie('the_cookie', { path: '/' }); + +*Note: when deleting a cookie, you must pass the exact same path, domain and secure options that were used to set the cookie, unless you're relying on the default options that is.* + +## Configuration + +By default the cookie value is encoded/decoded when writing/reading, using `encodeURIComponent`/`decodeURIComponent`. Bypass this by setting raw to true: + + $.cookie.raw = true; + +Turn on automatic storage of JSON objects passed as the cookie value. Assumes `JSON.stringify` and `JSON.parse`: + + $.cookie.json = true; + +## Cookie Options + +Cookie attributes can be set globally by setting properties of the `$.cookie.defaults` object or individually for each call to `$.cookie()` by passing a plain object to the options argument. Per-call options override the default options. + + expires: 365 + +Define lifetime of the cookie. Value can be a `Number` which will be interpreted as days from time of creation or a `Date` object. If omitted, the cookie becomes a session cookie. + + path: '/' + +Define the path where the cookie is valid. *By default the path of the cookie is the path of the page where the cookie was created (standard browser behavior).* If you want to make it available for instance across the entire domain use `path: '/'`. Default: path of page where the cookie was created. + + domain: 'example.com' + +Define the domain where the cookie is valid. Default: domain of page where the cookie was created. + + secure: true + +If true, the cookie transmission requires a secure protocol (https). Default: `false`. + +## Tests + +Requires Node. Startup server: + + $ node server.js + +Open in browser: + + $ open http://0.0.0.0:8124/test.html + +## Development + +- Source hosted at [GitHub](https://github.com/carhartl/jquery-cookie) +- Report issues, questions, feature requests on [GitHub Issues](https://github.com/carhartl/jquery-cookie/issues) + +Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change you make. + +## Authors + +[Klaus Hartl](https://github.com/carhartl) diff --git a/www/themes/profind/lib/cookie/jquery.cookie.js b/www/themes/profind/lib/cookie/jquery.cookie.js new file mode 100644 index 0000000..2d4c05a --- /dev/null +++ b/www/themes/profind/lib/cookie/jquery.cookie.js @@ -0,0 +1,72 @@ +/*! + * jQuery Cookie Plugin v1.3 + * https://github.com/carhartl/jquery-cookie + * + * Copyright 2011, Klaus Hartl + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://www.opensource.org/licenses/mit-license.php + * http://www.opensource.org/licenses/GPL-2.0 + */ +(function ($, document, undefined) { + + var pluses = /\+/g; + + function raw(s) { + return s; + } + + function decoded(s) { + return decodeURIComponent(s.replace(pluses, ' ')); + } + + var config = $.cookie = function (key, value, options) { + + // write + if (value !== undefined) { + options = $.extend({}, config.defaults, options); + + if (value === null) { + options.expires = -1; + } + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + value = config.json ? JSON.stringify(value) : String(value); + + return (document.cookie = [ + encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // read + var decode = config.raw ? raw : decoded; + var cookies = document.cookie.split('; '); + for (var i = 0, l = cookies.length; i < l; i++) { + var parts = cookies[i].split('='); + if (decode(parts.shift()) === key) { + var cookie = decode(parts.join('=')); + return config.json ? JSON.parse(cookie) : cookie; + } + } + + return null; + }; + + config.defaults = {}; + + $.removeCookie = function (key, options) { + if ($.cookie(key) !== null) { + $.cookie(key, null, options); + return true; + } + return false; + }; + +})(jQuery, document); diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.css b/www/themes/profind/lib/qtip2/jquery.qtip.css new file mode 100644 index 0000000..f354308 --- /dev/null +++ b/www/themes/profind/lib/qtip2/jquery.qtip.css @@ -0,0 +1,557 @@ +/* +* qTip2 - Pretty powerful tooltips +* http://craigsworks.com/projects/qtip2/ +* +* Version: nightly +* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com +* +* Dual licensed under MIT or GPLv2 licenses +* http://en.wikipedia.org/wiki/MIT_License +* http://en.wikipedia.org/wiki/GNU_General_Public_License +* +* Date: Mon Apr 2 13:46:17.0000000000 2012 +*/ + +/* Core qTip styles */ +.ui-tooltip, .qtip{ + position: absolute; + left: -28000px; + top: -28000px; + display: none; + + max-width: 280px; + min-width: 50px; + + font-size: 10.5px; + line-height: 12px; +} + + /* Fluid class for determining actual width in IE */ + .ui-tooltip-fluid{ + display: block; + visibility: hidden; + position: static !important; + float: left !important; + } + + .ui-tooltip-content{ + position: relative; + padding: 5px 9px; + overflow: hidden; + + border: 1px solid #000001; + + text-align: left; + word-wrap: break-word; + overflow: hidden; + } + + .ui-tooltip-titlebar{ + position: relative; + min-height: 14px; + padding: 5px 35px 5px 10px; + overflow: hidden; + + border: 1px solid #000001; + border-width: 1px 1px 0; + + font-weight: bold; + } + + .ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0px !important; } + + /*! Default close button class */ + .ui-tooltip-titlebar .ui-state-default{ + position: absolute; + right: 4px; + top: 50%; + margin-top: -9px; + + cursor: pointer; + outline: medium none; + + border-width: 1px; + border-style: solid; + } + + * html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */ + + .ui-tooltip-titlebar .ui-icon, + .ui-tooltip-icon .ui-icon{ + display: block; + text-indent: -1000em; + } + + .ui-tooltip-icon, .ui-tooltip-icon .ui-icon{ + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + } + + .ui-tooltip-icon .ui-icon{ + width: 18px; + height: 14px; + + text-align: center; + text-indent: 0; + font: normal bold 10px/13px Tahoma,sans-serif; + + color: inherit; + background: transparent none no-repeat -100em -100em; + } + + +/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */ +.ui-tooltip-focus{ + +} + +/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */ +.ui-tooltip-hover{ + +} + + +/*! Default tooltip style */ +.ui-tooltip-default .ui-tooltip-titlebar, +.ui-tooltip-default .ui-tooltip-content{ + border-color: #F1D031; + background-color: #FFFFA3; + color: #555; +} + + .ui-tooltip-default .ui-tooltip-titlebar{ + background-color: #FFEF93; + } + + .ui-tooltip-default .ui-tooltip-icon{ + border-color: #CCC; + background: #F1F1F1; + color: #777; + } + + .ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{ + border-color: #AAA; + color: #111; + } + +/* Tips plugin */ +.ui-tooltip .ui-tooltip-tip{ + margin: 0 auto; + overflow: hidden; + z-index: 10; +} + + .ui-tooltip .ui-tooltip-tip, + .ui-tooltip .ui-tooltip-tip *{ + position: absolute; + + line-height: 0.1px !important; + font-size: 0.1px !important; + color: #123456; + + background: transparent; + border: 0px dashed transparent; + } + + .ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; } + + +/* Modal plugin */ +#qtip-overlay{ + position: fixed; + left: -10000em; + top: -10000em; +} + + /* Applied to modals with show.modal.blur set to true */ + #qtip-overlay.blurs{ cursor: pointer; } + + /* Change opacity of overlay here */ + #qtip-overlay div{ + position: absolute; + left: 0; top: 0; + width: 100%; height: 100%; + + background-color: black; + + opacity: 0.7; + filter:alpha(opacity=70); + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; + } + +/*! Light tooltip style */ +.ui-tooltip-light .ui-tooltip-titlebar, +.ui-tooltip-light .ui-tooltip-content{ + border-color: #E2E2E2; + color: #454545; +} + + .ui-tooltip-light .ui-tooltip-content{ + background-color: white; + } + + .ui-tooltip-light .ui-tooltip-titlebar{ + background-color: #f1f1f1; + } + + +/*! Dark tooltip style */ +.ui-tooltip-dark .ui-tooltip-titlebar, +.ui-tooltip-dark .ui-tooltip-content{ + border-color: #303030; + color: #f3f3f3; +} + + .ui-tooltip-dark .ui-tooltip-content{ + background-color: #505050; + } + + .ui-tooltip-dark .ui-tooltip-titlebar{ + background-color: #404040; + } + + .ui-tooltip-dark .ui-tooltip-icon{ + border-color: #444; + } + + .ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/*! Cream tooltip style */ +.ui-tooltip-cream .ui-tooltip-titlebar, +.ui-tooltip-cream .ui-tooltip-content{ + border-color: #F9E98E; + color: #A27D35; +} + + .ui-tooltip-cream .ui-tooltip-content{ + background-color: #FBF7AA; + } + + .ui-tooltip-cream .ui-tooltip-titlebar{ + background-color: #F0DE7D; + } + + .ui-tooltip-cream .ui-state-default .ui-tooltip-icon{ + background-position: -82px 0; + } + + +/*! Red tooltip style */ +.ui-tooltip-red .ui-tooltip-titlebar, +.ui-tooltip-red .ui-tooltip-content{ + border-color: #D95252; + color: #912323; +} + + .ui-tooltip-red .ui-tooltip-content{ + background-color: #F78B83; + } + + .ui-tooltip-red .ui-tooltip-titlebar{ + background-color: #F06D65; + } + + .ui-tooltip-red .ui-state-default .ui-tooltip-icon{ + background-position: -102px 0; + } + + .ui-tooltip-red .ui-tooltip-icon{ + border-color: #D95252; + } + + .ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{ + border-color: #D95252; + } + + +/*! Green tooltip style */ +.ui-tooltip-green .ui-tooltip-titlebar, +.ui-tooltip-green .ui-tooltip-content{ + border-color: #90D93F; + color: #3F6219; +} + + .ui-tooltip-green .ui-tooltip-content{ + background-color: #CAED9E; + } + + .ui-tooltip-green .ui-tooltip-titlebar{ + background-color: #B0DE78; + } + + .ui-tooltip-green .ui-state-default .ui-tooltip-icon{ + background-position: -42px 0; + } + + +/*! Blue tooltip style */ +.ui-tooltip-blue .ui-tooltip-titlebar, +.ui-tooltip-blue .ui-tooltip-content{ + border-color: #ADD9ED; + color: #5E99BD; +} + + .ui-tooltip-blue .ui-tooltip-content{ + background-color: #E5F6FE; + } + + .ui-tooltip-blue .ui-tooltip-titlebar{ + background-color: #D0E9F5; + } + + .ui-tooltip-blue .ui-state-default .ui-tooltip-icon{ + background-position: -2px 0; + } + +/*! Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE6+, Safari 2+ */ +.ui-tooltip-shadow{ + -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); + box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); +} + + .ui-tooltip-shadow .ui-tooltip-titlebar, + .ui-tooltip-shadow .ui-tooltip-content{ + filter: progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3); + -ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3)"; + + _margin-bottom: -3px; /* IE6 */ + .margin-bottom: -3px; /* IE7 */ + } + + +/*! Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.ui-tooltip-rounded, +.ui-tooltip-rounded .ui-tooltip-content, +.ui-tooltip-tipsy, +.ui-tooltip-tipsy .ui-tooltip-content, +.ui-tooltip-youtube, +.ui-tooltip-youtube .ui-tooltip-content{ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; +} + +.ui-tooltip-rounded .ui-tooltip-titlebar, +.ui-tooltip-tipsy .ui-tooltip-titlebar, +.ui-tooltip-youtube .ui-tooltip-titlebar{ + -moz-border-radius: 5px 5px 0 0; + -webkit-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.ui-tooltip-rounded .ui-tooltip-titlebar + .ui-tooltip-content, +.ui-tooltip-tipsy .ui-tooltip-titlebar + .ui-tooltip-content, +.ui-tooltip-youtube .ui-tooltip-titlebar + .ui-tooltip-content{ + -moz-border-radius: 0 0 5px 5px; + -webkit-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + + +/*! Youtube tooltip style */ +.ui-tooltip-youtube{ + -webkit-box-shadow: 0 0 3px #333; + -moz-box-shadow: 0 0 3px #333; + box-shadow: 0 0 3px #333; +} + + .ui-tooltip-youtube .ui-tooltip-titlebar, + .ui-tooltip-youtube .ui-tooltip-content{ + _margin-bottom: 0; /* IE6 */ + .margin-bottom: 0; /* IE7 */ + + background: transparent; + background: rgba(0, 0, 0, 0.85); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)"; + + color: white; + border-color: #CCCCCC; + } + + .ui-tooltip-youtube .ui-tooltip-icon{ + border-color: #222; + } + + .ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/* jQuery TOOLS Tooltip style */ +.ui-tooltip-jtools{ + background: #232323; + background: rgba(0, 0, 0, 0.7); + background-image: -moz-linear-gradient(top, #717171, #232323); + background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323)); + + border: 2px solid #ddd; + border: 2px solid rgba(241,241,241,1); + + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + + -webkit-box-shadow: 0 0 12px #333; + -moz-box-shadow: 0 0 12px #333; + box-shadow: 0 0 12px #333; +} + + /* IE Specific */ + .ui-tooltip-jtools .ui-tooltip-titlebar{ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"; + } + .ui-tooltip-jtools .ui-tooltip-content{ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"; + } + + .ui-tooltip-jtools .ui-tooltip-titlebar, + .ui-tooltip-jtools .ui-tooltip-content{ + background: transparent; + color: white; + border: 0 dashed transparent; + } + + .ui-tooltip-jtools .ui-tooltip-icon{ + border-color: #555; + } + + .ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{ + border-color: #333; + } + + +/* Cluetip style */ +.ui-tooltip-cluetip{ + -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); +} + + .ui-tooltip-cluetip .ui-tooltip-titlebar{ + background-color: #87876A; + color: white; + border: 0 dashed transparent; + } + + .ui-tooltip-cluetip .ui-tooltip-content{ + background-color: #D9D9C2; + color: #111; + border: 0 dashed transparent; + } + + .ui-tooltip-cluetip .ui-tooltip-icon{ + border-color: #808064; + } + + .ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{ + border-color: #696952; + color: #696952; + } + + +/* Tipsy style */ +.ui-tooltip-tipsy{ + border: 0; +} + + .ui-tooltip-tipsy .ui-tooltip-titlebar, + .ui-tooltip-tipsy .ui-tooltip-content{ + _margin-bottom: 0; /* IE6 */ + .margin-bottom: 0; /* IE7 */ + + background: transparent; + background: rgba(0, 0, 0, .87); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)"; + + color: white; + border: 0px transparent; + + font-size: 11px; + font-family: 'Lucida Grande', sans-serif; + font-weight: bold; + line-height: 16px; + text-shadow: 0 1px black; + } + + .ui-tooltip-tipsy .ui-tooltip-titlebar{ + padding: 6px 35px 0 10; + } + + .ui-tooltip-tipsy .ui-tooltip-content{ + padding: 6px 10; + } + + .ui-tooltip-tipsy .ui-tooltip-icon{ + border-color: #222; + text-shadow: none; + } + + .ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/* Tipped style */ +.ui-tooltip-tipped{ + +} + + .ui-tooltip-tipped .ui-tooltip-titlebar, + .ui-tooltip-tipped .ui-tooltip-content{ + border: 3px solid #959FA9; + + filter: none; -ms-filter: none; + } + + .ui-tooltip-tipped .ui-tooltip-titlebar{ + background: #3A79B8; + background-image: -moz-linear-gradient(top, #3A79B8, #2E629D); + background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D)); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"; + + color: white; + font-weight: normal; + font-family: serif; + + border-bottom-width: 0; + -moz-border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + } + + .ui-tooltip-tipped .ui-tooltip-content{ + background-color: #F9F9F9; + color: #454545; + + -moz-border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + } + + .ui-tooltip-tipped .ui-tooltip-icon{ + border: 2px solid #285589; + background: #285589; + } + + .ui-tooltip-tipped .ui-tooltip-icon .ui-icon{ + background-color: #FBFBFB; + color: #555; + } + +/* IE9 fix - removes all filters */ +.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content, +.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{ + filter: none; + -ms-filter: none; +} + diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.js b/www/themes/profind/lib/qtip2/jquery.qtip.js new file mode 100644 index 0000000..ed0d724 --- /dev/null +++ b/www/themes/profind/lib/qtip2/jquery.qtip.js @@ -0,0 +1,3270 @@ +/* +* qTip2 - Pretty powerful tooltips +* http://craigsworks.com/projects/qtip2/ +* +* Version: nightly +* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com +* +* Dual licensed under MIT or GPLv2 licenses +* http://en.wikipedia.org/wiki/MIT_License +* http://en.wikipedia.org/wiki/GNU_General_Public_License +* +* Date: Mon Apr 2 13:46:17.0000000000 2012 +*/ + +/*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true */ +/*global window: false, jQuery: false, console: false, define: false */ + +// Uses AMD or browser globals to create a jQuery plugin. +(function(factory) { + if(typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else { + factory(jQuery); + } +} +(function($) { + + "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ + + // Munge the primitives - Paul Irish tip + var TRUE = true, + FALSE = false, + NULL = null, + undefined, + + // Shortcut vars + QTIP, PLUGINS, MOUSE, + usedIDs = {}, + uitooltip = 'ui-tooltip', + widget = 'ui-widget', + disabled = 'ui-state-disabled', + selector = 'div.qtip.'+uitooltip, + defaultClass = uitooltip + '-default', + focusClass = uitooltip + '-focus', + hoverClass = uitooltip + '-hover', + fluidClass = uitooltip + '-fluid', + hideOffset = '-31000px', + replaceSuffix = '_replacedByqTip', + oldtitle = 'oldtitle', + trackingBound; + + /* Thanks to Paul Irish for this one: http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ */ + function log() { + log.history = log.history || []; + log.history.push(arguments); + + // Make sure console is present + if('object' === typeof console) { + + // Setup console and arguments + var c = console[ console.warn ? 'warn' : 'log' ], + args = Array.prototype.slice.call(arguments), a; + + // Add qTip2 marker to first argument if it's a string + if(typeof arguments[0] === 'string') { args[0] = 'qTip2: ' + args[0]; } + + // Apply console.warn or .log if not supported + a = c.apply ? c.apply(console, args) : c(args); + } + } + +// Option object sanitizer +function sanitizeOptions(opts) +{ + var content; + + if(!opts || 'object' !== typeof opts) { return FALSE; } + + if(opts.metadata === NULL || 'object' !== typeof opts.metadata) { + opts.metadata = { + type: opts.metadata + }; + } + + if('content' in opts) { + if(opts.content === NULL || 'object' !== typeof opts.content || opts.content.jquery) { + opts.content = { + text: opts.content + }; + } + + content = opts.content.text || FALSE; + if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { + opts.content.text = FALSE; + } + + if('title' in opts.content) { + if(opts.content.title === NULL || 'object' !== typeof opts.content.title) { + opts.content.title = { + text: opts.content.title + }; + } + + content = opts.content.title.text || FALSE; + if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { + opts.content.title.text = FALSE; + } + } + } + + if('position' in opts) { + if(opts.position === NULL || 'object' !== typeof opts.position) { + opts.position = { + my: opts.position, + at: opts.position + }; + } + } + + if('show' in opts) { + if(opts.show === NULL || 'object' !== typeof opts.show) { + if(opts.show.jquery) { + opts.show = { target: opts.show }; + } + else { + opts.show = { event: opts.show }; + } + } + } + + if('hide' in opts) { + if(opts.hide === NULL || 'object' !== typeof opts.hide) { + if(opts.hide.jquery) { + opts.hide = { target: opts.hide }; + } + else { + opts.hide = { event: opts.hide }; + } + } + } + + if('style' in opts) { + if(opts.style === NULL || 'object' !== typeof opts.style) { + opts.style = { + classes: opts.style + }; + } + } + + // Sanitize plugin options + $.each(PLUGINS, function() { + if(this.sanitize) { this.sanitize(opts); } + }); + + return opts; +} + +/* +* Core plugin implementation +*/ +function QTip(target, options, id, attr) +{ + // Declare this reference + var self = this, + docBody = document.body, + tooltipID = uitooltip + '-' + id, + isPositioning = 0, + isDrawing = 0, + tooltip = $(), + namespace = '.qtip-' + id, + elements, cache; + + // Setup class attributes + self.id = id; + self.rendered = FALSE; + self.elements = elements = { target: target }; + self.timers = { img: {} }; + self.options = options; + self.checks = {}; + self.plugins = {}; + self.cache = cache = { + event: {}, + target: $(), + disabled: FALSE, + attr: attr, + onTarget: FALSE + }; + + /* + * Private core functions + */ + function convertNotation(notation) + { + var i = 0, obj, option = options, + + // Split notation into array + levels = notation.split('.'); + + // Loop through + while( option = option[ levels[i++] ] ) { + if(i < levels.length) { obj = option; } + } + + return [obj || options, levels.pop()]; + } + + function setWidget() { + var on = options.style.widget; + + tooltip.toggleClass(widget, on).toggleClass(defaultClass, options.style.def && !on); + elements.content.toggleClass(widget+'-content', on); + + if(elements.titlebar){ + elements.titlebar.toggleClass(widget+'-header', on); + } + if(elements.button){ + elements.button.toggleClass(uitooltip+'-icon', !on); + } + } + + function removeTitle(reposition) + { + if(elements.title) { + elements.titlebar.remove(); + elements.titlebar = elements.title = elements.button = NULL; + + // Reposition if enabled + if(reposition !== FALSE) { self.reposition(); } + } + } + + function createButton() + { + var button = options.content.title.button, + isString = typeof button === 'string', + close = isString ? button : 'Close tooltip'; + + if(elements.button) { elements.button.remove(); } + + // Use custom button if one was supplied by user, else use default + if(button.jquery) { + elements.button = button; + } + else { + elements.button = $('', { + 'class': 'ui-state-default ui-tooltip-close ' + (options.style.widget ? '' : uitooltip+'-icon'), + 'title': close, + 'aria-label': close + }) + .prepend( + $('', { + 'class': 'ui-icon ui-icon-close', + 'html': '×' + }) + ); + } + + // Create button and setup attributes + elements.button.appendTo(elements.titlebar) + .attr('role', 'button') + .click(function(event) { + if(!tooltip.hasClass(disabled)) { self.hide(event); } + return FALSE; + }); + + // Redraw the tooltip when we're done + self.redraw(); + } + + function createTitle() + { + var id = tooltipID+'-title'; + + // Destroy previous title element, if present + if(elements.titlebar) { removeTitle(); } + + // Create title bar and title elements + elements.titlebar = $('
    ', { + 'class': uitooltip + '-titlebar ' + (options.style.widget ? 'ui-widget-header' : '') + }) + .append( + elements.title = $('
    ', { + 'id': id, + 'class': uitooltip + '-title', + 'aria-atomic': TRUE + }) + ) + .insertBefore(elements.content) + + // Button-specific events + .delegate('.ui-tooltip-close', 'mousedown keydown mouseup keyup mouseout', function(event) { + $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down'); + }) + .delegate('.ui-tooltip-close', 'mouseover mouseout', function(event){ + $(this).toggleClass('ui-state-hover', event.type === 'mouseover'); + }); + + // Create button if enabled + if(options.content.title.button) { createButton(); } + + // Redraw the tooltip dimensions if it's rendered + else if(self.rendered){ self.redraw(); } + } + + function updateButton(button) + { + var elem = elements.button, + title = elements.title; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered) { return FALSE; } + + if(!button) { + elem.remove(); + } + else { + if(!title) { + createTitle(); + } + createButton(); + } + } + + function updateTitle(content, reposition) + { + var elem = elements.title; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, cache.event, self); + } + + // Remove title if callback returns false or null/undefined (but not '') + if(content === FALSE || (!content && content !== '')) { return removeTitle(FALSE); } + + // Append new content if its a DOM array and show it if hidden + else if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Redraw and reposition + self.redraw(); + if(reposition !== FALSE && self.rendered && tooltip.is(':visible')) { + self.reposition(cache.event); + } + } + + function updateContent(content, reposition) + { + var elem = elements.content; + + // Make sure tooltip is rendered and content is defined. If not return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, cache.event, self) || ''; + } + + // Append new content if its a DOM array and show it if hidden + if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Image detection + function detectImages(next) { + var images, srcs = {}; + + function imageLoad(image) { + // Clear src from object and any timers and events associated with the image + if(image) { + delete srcs[image.src]; + clearTimeout(self.timers.img[image.src]); + $(image).unbind(namespace); + } + + // If queue is empty after image removal, update tooltip and continue the queue + if($.isEmptyObject(srcs)) { + self.redraw(); + if(reposition !== FALSE) { + self.reposition(cache.event); + } + + next(); + } + } + + // Find all content images without dimensions, and if no images were found, continue + if((images = elem.find('img[src]:not([height]):not([width])')).length === 0) { return imageLoad(); } + + // Apply timer to each image to poll for dimensions + images.each(function(i, elem) { + // Skip if the src is already present + if(srcs[elem.src] !== undefined) { return; } + + // Keep track of how many times we poll for image dimensions. + // If it doesn't return in a reasonable amount of time, it's better + // to display the tooltip, rather than hold up the queue. + var iterations = 0, maxIterations = 3; + + (function timer(){ + // When the dimensions are found, remove the image from the queue + if(elem.height || elem.width || (iterations > maxIterations)) { return imageLoad(elem); } + + // Increase iterations and restart timer + iterations += 1; + self.timers.img[elem.src] = setTimeout(timer, 700); + }()); + + // Also apply regular load/error event handlers + $(elem).bind('error'+namespace+' load'+namespace, function(){ imageLoad(this); }); + + // Store the src and element in our object + srcs[elem.src] = elem; + }); + } + + /* + * If we're still rendering... insert into 'fx' queue our image dimension + * checker which will halt the showing of the tooltip until image dimensions + * can be detected properly. + */ + if(self.rendered < 0) { tooltip.queue('fx', detectImages); } + + // We're fully rendered, so reset isDrawing flag and proceed without queue delay + else { isDrawing = 0; detectImages($.noop); } + + return self; + } + + function assignEvents() + { + var posOptions = options.position, + targets = { + show: options.show.target, + hide: options.hide.target, + viewport: $(posOptions.viewport), + document: $(document), + body: $(document.body), + window: $(window) + }, + events = { + show: $.trim('' + options.show.event).split(' '), + hide: $.trim('' + options.hide.event).split(' ') + }, + IE6 = $.browser.msie && parseInt($.browser.version, 10) === 6; + + // Define show event method + function showMethod(event) + { + if(tooltip.hasClass(disabled)) { return FALSE; } + + // Clear hide timers + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Start show timer + var callback = function(){ self.toggle(TRUE, event); }; + if(options.show.delay > 0) { + self.timers.show = setTimeout(callback, options.show.delay); + } + else{ callback(); } + } + + // Define hide method + function hideMethod(event) + { + if(tooltip.hasClass(disabled) || isPositioning || isDrawing) { return FALSE; } + + // Check if new target was actually the tooltip element + var relatedTarget = $(event.relatedTarget || event.target), + ontoTooltip = relatedTarget.closest(selector)[0] === tooltip[0], + ontoTarget = relatedTarget[0] === targets.show[0]; + + // Clear timers and stop animation queue + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Prevent hiding if tooltip is fixed and event target is the tooltip. Or if mouse positioning is enabled and cursor momentarily overlaps + if((posOptions.target === 'mouse' && ontoTooltip) || (options.hide.fixed && ((/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget)))) { + try { event.preventDefault(); event.stopImmediatePropagation(); } catch(e) {} return; + } + + // If tooltip has displayed, start hide timer + if(options.hide.delay > 0) { + self.timers.hide = setTimeout(function(){ self.hide(event); }, options.hide.delay); + } + else{ self.hide(event); } + } + + // Define inactive method + function inactiveMethod(event) + { + if(tooltip.hasClass(disabled)) { return FALSE; } + + // Clear timer + clearTimeout(self.timers.inactive); + self.timers.inactive = setTimeout(function(){ self.hide(event); }, options.hide.inactive); + } + + function repositionMethod(event) { + if(tooltip.is(':visible')) { self.reposition(event); } + } + + // On mouseenter/mouseleave... + tooltip.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { + var state = event.type === 'mouseenter'; + + // Focus the tooltip on mouseenter (z-index stacking) + if(state) { self.focus(event); } + + // Add hover class + tooltip.toggleClass(hoverClass, state); + }); + + // Enable hide.fixed + if(options.hide.fixed) { + // Add tooltip as a hide target + targets.hide = targets.hide.add(tooltip); + + // Clear hide timer on tooltip hover to prevent it from closing + tooltip.bind('mouseover'+namespace, function() { + if(!tooltip.hasClass(disabled)) { clearTimeout(self.timers.hide); } + }); + } + + // If using mouseout/mouseleave as a hide event... + if(/mouse(out|leave)/i.test(options.hide.event)) { + // Hide tooltips when leaving current window/frame (but not select/option elements) + if(options.hide.leave === 'window') { + targets.window.bind('mouseout'+namespace+' blur'+namespace, function(event) { + if(/select|option/.test(event.target) && !event.relatedTarget) { self.hide(event); } + }); + } + } + + /* + * Make sure hoverIntent functions properly by using mouseleave to clear show timer if + * mouseenter/mouseout is used for show.event, even if it isn't in the users options. + */ + else if(/mouse(over|enter)/i.test(options.show.event)) { + targets.hide.bind('mouseleave'+namespace, function(event) { + clearTimeout(self.timers.show); + }); + } + + // Hide tooltip on document mousedown if unfocus events are enabled + if(('' + options.hide.event).indexOf('unfocus') > -1) { + posOptions.container.closest('html').bind('mousedown'+namespace, function(event) { + var elem = $(event.target), + enabled = !tooltip.hasClass(disabled) && tooltip.is(':visible'), + isAncestor = elem.parents(selector).filter(tooltip[0]).length > 0; + + if(elem[0] !== target[0] && elem[0] !== tooltip[0] && !isAncestor && + !target.has(elem[0]).length && !elem.attr('disabled') + ) { + self.hide(event); + } + }); + } + + // Check if the tooltip hides when inactive + if('number' === typeof options.hide.inactive) { + // Bind inactive method to target as a custom event + targets.show.bind('qtip-'+id+'-inactive', inactiveMethod); + + // Define events which reset the 'inactive' event handler + $.each(QTIP.inactiveEvents, function(index, type){ + targets.hide.add(elements.tooltip).bind(type+namespace+'-inactive', inactiveMethod); + }); + } + + // Apply hide events + $.each(events.hide, function(index, type) { + var showIndex = $.inArray(type, events.show), + targetHide = $(targets.hide); + + // Both events and targets are identical, apply events using a toggle + if((showIndex > -1 && targetHide.add(targets.show).length === targetHide.length) || type === 'unfocus') + { + targets.show.bind(type+namespace, function(event) { + if(tooltip.is(':visible')) { hideMethod(event); } + else { showMethod(event); } + }); + + // Don't bind the event again + delete events.show[ showIndex ]; + } + + // Events are not identical, bind normally + else { targets.hide.bind(type+namespace, hideMethod); } + }); + + // Apply show events + $.each(events.show, function(index, type) { + targets.show.bind(type+namespace, showMethod); + }); + + // Check if the tooltip hides when mouse is moved a certain distance + if('number' === typeof options.hide.distance) { + // Bind mousemove to target to detect distance difference + targets.show.add(tooltip).bind('mousemove'+namespace, function(event) { + var origin = cache.origin || {}, + limit = options.hide.distance, + abs = Math.abs; + + // Check if the movement has gone beyond the limit, and hide it if so + if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) { + self.hide(event); + } + }); + } + + // Mouse positioning events + if(posOptions.target === 'mouse') { + // Cache mousemove coords on show targets + targets.show.bind('mousemove'+namespace, function(event) { + MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; + }); + + // If mouse adjustment is on... + if(posOptions.adjust.mouse) { + // Apply a mouseleave event so we don't get problems with overlapping + if(options.hide.event) { + // Hide when we leave the tooltip and not onto the show target + tooltip.bind('mouseleave'+namespace, function(event) { + if((event.relatedTarget || event.target) !== targets.show[0]) { self.hide(event); } + }); + + // Track if we're on the target or not + elements.target.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { + cache.onTarget = event.type === 'mouseenter'; + }); + } + + // Update tooltip position on mousemove + targets.document.bind('mousemove'+namespace, function(event) { + // Update the tooltip position only if the tooltip is visible and adjustment is enabled + if(cache.onTarget && !tooltip.hasClass(disabled) && tooltip.is(':visible')) { + self.reposition(event || MOUSE); + } + }); + } + } + + // Adjust positions of the tooltip on window resize if enabled + if(posOptions.adjust.resize || targets.viewport.length) { + ($.event.special.resize ? targets.viewport : targets.window).bind('resize'+namespace, repositionMethod); + } + + // Adjust tooltip position on scroll if screen adjustment is enabled + if(targets.viewport.length || (IE6 && tooltip.css('position') === 'fixed')) { + targets.viewport.bind('scroll'+namespace, repositionMethod); + } + } + + function unassignEvents() + { + var targets = [ + options.show.target[0], + options.hide.target[0], + self.rendered && elements.tooltip[0], + options.position.container[0], + options.position.viewport[0], + window, + document + ]; + + // Check if tooltip is rendered + if(self.rendered) { + $([]).pushStack( $.grep(targets, function(i){ return typeof i === 'object'; }) ).unbind(namespace); + } + + // Tooltip isn't yet rendered, remove render event + else { options.show.target.unbind(namespace+'-create'); } + } + + // Setup builtin .set() option checks + self.checks.builtin = { + // Core checks + '^id$': function(obj, o, v) { + var id = v === TRUE ? QTIP.nextid : v, + tooltipID = uitooltip + '-' + id; + + if(id !== FALSE && id.length > 0 && !$('#'+tooltipID).length) { + tooltip[0].id = tooltipID; + elements.content[0].id = tooltipID + '-content'; + elements.title[0].id = tooltipID + '-title'; + } + }, + + // Content checks + '^content.text$': function(obj, o, v){ updateContent(v); }, + '^content.title.text$': function(obj, o, v) { + // Remove title if content is null + if(!v) { return removeTitle(); } + + // If title isn't already created, create it now and update + if(!elements.title && v) { createTitle(); } + updateTitle(v); + }, + '^content.title.button$': function(obj, o, v){ updateButton(v); }, + + // Position checks + '^position.(my|at)$': function(obj, o, v){ + // Parse new corner value into Corner objecct + if('string' === typeof v) { + obj[o] = new PLUGINS.Corner(v); + } + }, + '^position.container$': function(obj, o, v){ + if(self.rendered) { tooltip.appendTo(v); } + }, + + // Show checks + '^show.ready$': function() { + if(!self.rendered) { self.render(1); } + else { self.toggle(TRUE); } + }, + + // Style checks + '^style.classes$': function(obj, o, v) { + tooltip.attr('class', uitooltip + ' qtip ui-helper-reset ' + v); + }, + '^style.widget|content.title': setWidget, + + // Events check + '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) { + tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v); + }, + + // Properties which require event reassignment + '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() { + var posOptions = options.position; + + // Set tracking flag + tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse); + + // Reassign events + unassignEvents(); assignEvents(); + } + }; + + /* + * Public API methods + */ + $.extend(self, { + render: function(show) + { + if(self.rendered) { return self; } // If tooltip has already been rendered, exit + + var text = options.content.text, + title = options.content.title.text, + posOptions = options.position, + callback = $.Event('tooltiprender'); + + // Add ARIA attributes to target + $.attr(target[0], 'aria-describedby', tooltipID); + + // Create tooltip element + tooltip = elements.tooltip = $('
    ', { + 'id': tooltipID, + 'class': uitooltip + ' qtip ui-helper-reset ' + defaultClass + ' ' + options.style.classes + ' '+ uitooltip + '-pos-' + options.position.my.abbrev(), + 'width': options.style.width || '', + 'height': options.style.height || '', + 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse, + + /* ARIA specific attributes */ + 'role': 'alert', + 'aria-live': 'polite', + 'aria-atomic': FALSE, + 'aria-describedby': tooltipID + '-content', + 'aria-hidden': TRUE + }) + .toggleClass(disabled, cache.disabled) + .data('qtip', self) + .appendTo(options.position.container) + .append( + // Create content element + elements.content = $('
    ', { + 'class': uitooltip + '-content', + 'id': tooltipID + '-content', + 'aria-atomic': TRUE + }) + ); + + // Set rendered flag and prevent redundant redraw/reposition calls for now + self.rendered = -1; + isDrawing = 1; isPositioning = 1; + + // Create title... + if(title) { + createTitle(); + + // Update title only if its not a callback (called in toggle if so) + if(!$.isFunction(title)) { updateTitle(title, FALSE); } + } + + // Set proper rendered flag and update content if not a callback function (called in toggle) + if(!$.isFunction(text)) { updateContent(text, FALSE); } + self.rendered = TRUE; + + // Setup widget classes + setWidget(); + + // Assign passed event callbacks (before plugins!) + $.each(options.events, function(name, callback) { + if($.isFunction(callback)) { + tooltip.bind(name === 'toggle' ? 'tooltipshow tooltiphide' : 'tooltip'+name, callback); + } + }); + + // Initialize 'render' plugins + $.each(PLUGINS, function() { + if(this.initialize === 'render') { this(self); } + }); + + // Assign events + assignEvents(); + + /* Queue this part of the render process in our fx queue so we can + * load images before the tooltip renders fully. + * + * See: updateContent method + */ + tooltip.queue('fx', function(next) { + // Trigger tooltiprender event and pass original triggering event as original + callback.originalEvent = cache.event; + tooltip.trigger(callback, [self]); + + // Reset flags + isDrawing = 0; isPositioning = 0; + + // Redraw the tooltip manually now we're fully rendered + self.redraw(); + + // Show tooltip if needed + if(options.show.ready || show) { + self.toggle(TRUE, cache.event, FALSE); + } + + next(); // Move on to next method in queue + }); + + return self; + }, + + get: function(notation) + { + var result, o; + + switch(notation.toLowerCase()) + { + case 'dimensions': + result = { + height: tooltip.outerHeight(), width: tooltip.outerWidth() + }; + break; + + case 'offset': + result = PLUGINS.offset(tooltip, options.position.container); + break; + + default: + o = convertNotation(notation.toLowerCase()); + result = o[0][ o[1] ]; + result = result.precedance ? result.string() : result; + break; + } + + return result; + }, + + set: function(option, value) + { + var rmove = /^position\.(my|at|adjust|target|container)|style|content|show\.ready/i, + rdraw = /^content\.(title|attr)|style/i, + reposition = FALSE, + redraw = FALSE, + checks = self.checks, + name; + + function callback(notation, args) { + var category, rule, match; + + for(category in checks) { + for(rule in checks[category]) { + if(match = (new RegExp(rule, 'i')).exec(notation)) { + args.push(match); + checks[category][rule].apply(self, args); + } + } + } + } + + // Convert singular option/value pair into object form + if('string' === typeof option) { + name = option; option = {}; option[name] = value; + } + else { option = $.extend(TRUE, {}, option); } + + // Set all of the defined options to their new values + $.each(option, function(notation, value) { + var obj = convertNotation( notation.toLowerCase() ), previous; + + // Set new obj value + previous = obj[0][ obj[1] ]; + obj[0][ obj[1] ] = 'object' === typeof value && value.nodeType ? $(value) : value; + + // Set the new params for the callback + option[notation] = [obj[0], obj[1], value, previous]; + + // Also check if we need to reposition / redraw + reposition = rmove.test(notation) || reposition; + redraw = rdraw.test(notation) || redraw; + }); + + // Re-sanitize options + sanitizeOptions(options); + + /* + * Execute any valid callbacks for the set options + * Also set isPositioning/isDrawing so we don't get loads of redundant repositioning + * and redraw calls. + */ + isPositioning = isDrawing = 1; $.each(option, callback); isPositioning = isDrawing = 0; + + // Update position / redraw if needed + if(tooltip.is(':visible') && self.rendered) { + if(reposition) { + self.reposition( options.position.target === 'mouse' ? NULL : cache.event ); + } + if(redraw) { self.redraw(); } + } + + return self; + }, + + toggle: function(state, event) + { + // Render the tooltip if showing and it isn't already + if(!self.rendered) { return state ? self.render(1) : self; } + + var type = state ? 'show' : 'hide', + opts = options[type], + visible = tooltip.is(':visible'), + sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target, + eventAsTarget = event && opts.target.add(event.target).length !== opts.target.length, + posOptions = options.position, + contentOptions = options.content, + delay, + callback; + + // Detect state if valid one isn't provided + if((typeof state).search('boolean|number')) { state = !visible; } + + // Return if element is already in correct state + if(!tooltip.is(':animated') && visible === state && sameTarget) { return self; } + + // Try to prevent flickering when tooltip overlaps show element + if(event) { + if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) && + options.show.target.add(event.target).length === options.show.target.length && + tooltip.has(event.relatedTarget).length) { + return self; + } + + // Cache event + cache.event = $.extend({}, event); + } + + // Call API methods + callback = $.Event('tooltip'+type); + callback.originalEvent = event ? cache.event : NULL; + tooltip.trigger(callback, [self, 90]); + if(callback.isDefaultPrevented()){ return self; } + + // Set ARIA hidden status attribute + $.attr(tooltip[0], 'aria-hidden', !!!state); + + // Execute state specific properties + if(state) { + // Store show origin coordinates + cache.origin = $.extend({}, MOUSE); + + // Focus the tooltip + self.focus(event); + + // Update tooltip content & title if it's a dynamic function + if($.isFunction(contentOptions.text)) { updateContent(contentOptions.text, FALSE); } + if($.isFunction(contentOptions.title.text)) { updateTitle(contentOptions.title.text, FALSE); } + + // Cache mousemove events for positioning purposes (if not already tracking) + if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) { + $(document).bind('mousemove.qtip', function(event) { + MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; + }); + trackingBound = TRUE; + } + + // Update the tooltip position + self.reposition(event, arguments[2]); + + // Hide other tooltips if tooltip is solo, using it as the context + if((callback.solo = !!opts.solo)) { $(selector, opts.solo).not(tooltip).qtip('hide', callback); } + } + else { + // Clear show timer if we're hiding + clearTimeout(self.timers.show); + + // Remove cached origin on hide + delete cache.origin; + + // Remove mouse tracking event if not needed (all tracking qTips are hidden) + if(trackingBound && !$(selector+'[tracking="true"]:visible', opts.solo).not(tooltip).length) { + $(document).unbind('mousemove.qtip'); + trackingBound = FALSE; + } + + // Blur the tooltip + self.blur(event); + } + + // Define post-animation, state specific properties + function after() { + if(state) { + // Prevent antialias from disappearing in IE by removing filter + if($.browser.msie) { tooltip[0].style.removeAttribute('filter'); } + + // Remove overflow setting to prevent tip bugs + tooltip.css('overflow', ''); + + // Autofocus elements if enabled + if('string' === typeof opts.autofocus) { + $(opts.autofocus, tooltip).focus(); + } + + // If set, hide tooltip when inactive for delay period + opts.target.trigger('qtip-'+id+'-inactive'); + } + else { + // Reset CSS states + tooltip.css({ + display: '', + visibility: '', + opacity: '', + left: '', + top: '' + }); + } + + // Call API method + callback = $.Event('tooltip'+(state ? 'visible' : 'hidden')); + callback.originalEvent = event ? cache.event : NULL; + tooltip.trigger(callback, [self]); + } + + // Clear/stop animation + tooltip.stop(eventAsTarget, !eventAsTarget); + + // If no effect type is supplied, use a simple toggle + if(opts.effect === FALSE) { + tooltip[ type ](); + after.call(tooltip); + } + + // Use custom function if provided + else if($.isFunction(opts.effect)) { + opts.effect.call(tooltip, self); + tooltip.queue('fx', function(n){ after(); n(); }); + } + + // Use basic fade function by default + else { tooltip.fadeTo(90, state ? 1 : 0, after); } + + // If inactive hide method is set, active it + if(state) { opts.target.trigger('qtip-'+id+'-inactive'); } + + return self; + }, + + show: function(event){ return self.toggle(TRUE, event); }, + + hide: function(event){ return self.toggle(FALSE, event); }, + + focus: function(event) + { + if(!self.rendered) { return self; } + + var qtips = $(selector), + curIndex = parseInt(tooltip[0].style.zIndex, 10), + newIndex = QTIP.zindex + qtips.length, + cachedEvent = $.extend({}, event), + focusedElem, callback; + + // Only update the z-index if it has changed and tooltip is not already focused + if(!tooltip.hasClass(focusClass)) + { + // Call API method + callback = $.Event('tooltipfocus'); + callback.originalEvent = cachedEvent; + tooltip.trigger(callback, [self, newIndex]); + + // If default action wasn't prevented... + if(!callback.isDefaultPrevented()) { + // Only update z-index's if they've changed + if(curIndex !== newIndex) { + // Reduce our z-index's and keep them properly ordered + qtips.each(function() { + if(this.style.zIndex > curIndex) { + this.style.zIndex = this.style.zIndex - 1; + } + }); + + // Fire blur event for focused tooltip + qtips.filter('.' + focusClass).qtip('blur', cachedEvent); + } + + // Set the new z-index + tooltip.addClass(focusClass)[0].style.zIndex = newIndex; + } + } + + return self; + }, + + blur: function(event) { + var cachedEvent = $.extend({}, event), + callback; + + // Set focused status to FALSE + tooltip.removeClass(focusClass); + + // Trigger blur event + callback = $.Event('tooltipblur'); + callback.originalEvent = cachedEvent; + tooltip.trigger(callback, [self]); + + return self; + }, + + reposition: function(event, effect) + { + if(!self.rendered || isPositioning) { return self; } + + // Set positioning flag + isPositioning = 1; + + var target = options.position.target, + posOptions = options.position, + my = posOptions.my, + at = posOptions.at, + adjust = posOptions.adjust, + method = adjust.method.split(' '), + elemWidth = tooltip.outerWidth(), + elemHeight = tooltip.outerHeight(), + targetWidth = 0, + targetHeight = 0, + callback = $.Event('tooltipmove'), + fixed = tooltip.css('position') === 'fixed', + viewport = posOptions.viewport, + position = { left: 0, top: 0 }, + container = posOptions.container, + flipoffset = FALSE, + tip = self.plugins.tip, + readjust = { + // Axis detection and readjustment indicator + horizontal: method[0], + vertical: (method[1] = method[1] || method[0]), + enabled: viewport.jquery && target[0] !== window && target[0] !== docBody && adjust.method !== 'none', + + // Reposition methods + left: function(posLeft) { + var isShift = readjust.horizontal === 'shift', + viewportScroll = -container.offset.left + viewport.offset.left + viewport.scrollLeft, + myWidth = my.x === 'left' ? elemWidth : my.x === 'right' ? -elemWidth : -elemWidth / 2, + atWidth = at.x === 'left' ? targetWidth : at.x === 'right' ? -targetWidth : -targetWidth / 2, + tipWidth = tip && tip.size ? tip.size.width || 0 : 0, + tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' && !isShift ? tipWidth : 0, + overflowLeft = viewportScroll - posLeft + tipAdjust, + overflowRight = posLeft + elemWidth - viewport.width - viewportScroll + tipAdjust, + offset = myWidth - (my.precedance === 'x' || my.x === my.y ? atWidth : 0) - (at.x === 'center' ? targetWidth / 2 : 0), + isCenter = my.x === 'center'; + + // Optional 'shift' style repositioning + if(isShift) { + tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' ? tipWidth : 0; + offset = (my.x === 'left' ? 1 : -1) * myWidth - tipAdjust; + + // Adjust position but keep it within viewport dimensions + position.left += overflowLeft > 0 ? overflowLeft : overflowRight > 0 ? -overflowRight : 0; + position.left = Math.max( + -container.offset.left + viewport.offset.left + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0), + posLeft - offset, + Math.min( + Math.max(-container.offset.left + viewport.offset.left + viewport.width, posLeft + offset), + position.left + ) + ); + } + + // Default 'flip' repositioning + else { + if(overflowLeft > 0 && (my.x !== 'left' || overflowRight > 0)) { + position.left -= offset; + } + else if(overflowRight > 0 && (my.x !== 'right' || overflowLeft > 0) ) { + position.left -= isCenter ? -offset : offset; + } + if(position.left !== posLeft && isCenter) { position.left -= adjust.x; } + + // Make sure we haven't made things worse with the adjustment and return the adjusted difference + if(position.left < viewportScroll && -position.left > overflowRight) { position.left = posLeft; } + } + + return position.left - posLeft; + }, + top: function(posTop) { + var isShift = readjust.vertical === 'shift', + viewportScroll = -container.offset.top + viewport.offset.top + viewport.scrollTop, + myHeight = my.y === 'top' ? elemHeight : my.y === 'bottom' ? -elemHeight : -elemHeight / 2, + atHeight = at.y === 'top' ? targetHeight : at.y === 'bottom' ? -targetHeight : -targetHeight / 2, + tipHeight = tip && tip.size ? tip.size.height || 0 : 0, + tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' && !isShift ? tipHeight : 0, + overflowTop = viewportScroll - posTop + tipAdjust, + overflowBottom = posTop + elemHeight - viewport.height - viewportScroll + tipAdjust, + offset = myHeight - (my.precedance === 'y' || my.x === my.y ? atHeight : 0) - (at.y === 'center' ? targetHeight / 2 : 0), + isCenter = my.y === 'center'; + + // Optional 'shift' style repositioning + if(isShift) { + tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' ? tipHeight : 0; + offset = (my.y === 'top' ? 1 : -1) * myHeight - tipAdjust; + + // Adjust position but keep it within viewport dimensions + position.top += overflowTop > 0 ? overflowTop : overflowBottom > 0 ? -overflowBottom : 0; + position.top = Math.max( + -container.offset.top + viewport.offset.top + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0), + posTop - offset, + Math.min( + Math.max(-container.offset.top + viewport.offset.top + viewport.height, posTop + offset), + position.top + ) + ); + } + + // Default 'flip' repositioning + else { + if(overflowTop > 0 && (my.y !== 'top' || overflowBottom > 0)) { + position.top -= offset; + } + else if(overflowBottom > 0 && (my.y !== 'bottom' || overflowTop > 0) ) { + position.top -= isCenter ? -offset : offset; + } + if(position.top !== posTop && isCenter) { position.top -= adjust.y; } + + // Make sure we haven't made things worse with the adjustment and return the adjusted difference + if(position.top < 0 && -position.top > overflowBottom) { position.top = posTop; } + } + + return position.top - posTop; + } + }, + win; + + // Check if absolute position was passed + if($.isArray(target) && target.length === 2) { + // Force left top and set position + at = { x: 'left', y: 'top' }; + position = { left: target[0], top: target[1] }; + } + + // Check if mouse was the target + else if(target === 'mouse' && ((event && event.pageX) || cache.event.pageX)) { + // Force left top to allow flipping + at = { x: 'left', y: 'top' }; + + // Use cached event if one isn't available for positioning + event = (event && (event.type === 'resize' || event.type === 'scroll') ? cache.event : + event && event.pageX && event.type === 'mousemove' ? event : + MOUSE && MOUSE.pageX && (adjust.mouse || !event || !event.pageX) ? { pageX: MOUSE.pageX, pageY: MOUSE.pageY } : + !adjust.mouse && cache.origin && cache.origin.pageX && options.show.distance ? cache.origin : + event) || event || cache.event || MOUSE || {}; + + // Use event coordinates for position + position = { top: event.pageY, left: event.pageX }; + } + + // Target wasn't mouse or absolute... + else { + // Check if event targetting is being used + if(target === 'event') { + if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') { + target = cache.target = $(event.target); + } + else { + target = cache.target; + } + } + else { + target = cache.target = $(target.jquery ? target : elements.target); + } + + // Parse the target into a jQuery object and make sure there's an element present + target = $(target).eq(0); + if(target.length === 0) { return self; } + + // Check if window or document is the target + else if(target[0] === document || target[0] === window) { + targetWidth = PLUGINS.iOS ? window.innerWidth : target.width(); + targetHeight = PLUGINS.iOS ? window.innerHeight : target.height(); + + if(target[0] === window) { + position = { + top: (viewport || target).scrollTop(), + left: (viewport || target).scrollLeft() + }; + } + } + + // Use Imagemap/SVG plugins if needed + else if(target.is('area') && PLUGINS.imagemap) { + position = PLUGINS.imagemap(target, at, readjust.enabled ? method : FALSE); + } + else if(target[0].namespaceURI === 'http://www.w3.org/2000/svg' && PLUGINS.svg) { + position = PLUGINS.svg(target, at); + } + + else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + + position = PLUGINS.offset(target, container); + } + + // Parse returned plugin values into proper variables + if(position.offset) { + targetWidth = position.width; + targetHeight = position.height; + flipoffset = position.flipoffset; + position = position.offset; + } + + // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2 - v4.0) + if((PLUGINS.iOS < 4.1 && PLUGINS.iOS > 3.1) || PLUGINS.iOS == 4.3 || (!PLUGINS.iOS && fixed)) { + win = $(window); + position.left -= win.scrollLeft(); + position.top -= win.scrollTop(); + } + + // Adjust position relative to target + position.left += at.x === 'right' ? targetWidth : at.x === 'center' ? targetWidth / 2 : 0; + position.top += at.y === 'bottom' ? targetHeight : at.y === 'center' ? targetHeight / 2 : 0; + } + + // Adjust position relative to tooltip + position.left += adjust.x + (my.x === 'right' ? -elemWidth : my.x === 'center' ? -elemWidth / 2 : 0); + position.top += adjust.y + (my.y === 'bottom' ? -elemHeight : my.y === 'center' ? -elemHeight / 2 : 0); + + // Calculate collision offset values if viewport positioning is enabled + if(readjust.enabled) { + // Cache our viewport details + viewport = { + elem: viewport, + height: viewport[ (viewport[0] === window ? 'h' : 'outerH') + 'eight' ](), + width: viewport[ (viewport[0] === window ? 'w' : 'outerW') + 'idth' ](), + scrollLeft: fixed ? 0 : viewport.scrollLeft(), + scrollTop: fixed ? 0 : viewport.scrollTop(), + offset: viewport.offset() || { left: 0, top: 0 } + }; + container = { + elem: container, + scrollLeft: container.scrollLeft(), + scrollTop: container.scrollTop(), + offset: container.offset() || { left: 0, top: 0 } + }; + + // Adjust position based onviewport and adjustment options + position.adjusted = { + left: readjust.horizontal !== 'none' ? readjust.left(position.left) : 0, + top: readjust.vertical !== 'none' ? readjust.top(position.top) : 0 + }; + + // Set tooltip position class + if(position.adjusted.left + position.adjusted.top) { + tooltip.attr('class', tooltip[0].className.replace(/ui-tooltip-pos-\w+/i, uitooltip + '-pos-' + my.abbrev())); + } + + // Apply flip offsets supplied by positioning plugins + if(flipoffset && position.adjusted.left) { position.left += flipoffset.left; } + if(flipoffset && position.adjusted.top) { position.top += flipoffset.top; } + } + + //Viewport adjustment is disabled, set values to zero + else { position.adjusted = { left: 0, top: 0 }; } + + // Call API method + callback.originalEvent = $.extend({}, event); + tooltip.trigger(callback, [self, position, viewport.elem || viewport]); + if(callback.isDefaultPrevented()){ return self; } + delete position.adjusted; + + // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly + if(effect === FALSE || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) { + tooltip.css(position); + } + + // Use custom function if provided + else if($.isFunction(posOptions.effect)) { + posOptions.effect.call(tooltip, self, $.extend({}, position)); + tooltip.queue(function(next) { + // Reset attributes to avoid cross-browser rendering bugs + $(this).css({ opacity: '', height: '' }); + if($.browser.msie) { this.style.removeAttribute('filter'); } + + next(); + }); + } + + // Set positioning flag + isPositioning = 0; + + return self; + }, + + // Max/min width simulator function for all browsers.. yeaaah! + redraw: function() + { + if(self.rendered < 1 || isDrawing) { return self; } + + var container = options.position.container, + perc, width, max, min; + + // Set drawing flag + isDrawing = 1; + + // If tooltip has a set height, just set it... like a boss! + if(options.style.height) { tooltip.css('height', options.style.height); } + + // If tooltip has a set width, just set it... like a boss! + if(options.style.width) { tooltip.css('width', options.style.width); } + + // Otherwise simualte max/min width... + else { + // Reset width and add fluid class + tooltip.css('width', '').addClass(fluidClass); + + // Grab our tooltip width (add 1 so we don't get wrapping problems.. huzzah!) + width = tooltip.width() + 1; + + // Grab our max/min properties + max = tooltip.css('max-width') || ''; + min = tooltip.css('min-width') || ''; + + // Parse into proper pixel values + perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0; + max = ((max.indexOf('%') > -1 ? perc : 1) * parseInt(max, 10)) || width; + min = ((min.indexOf('%') > -1 ? perc : 1) * parseInt(min, 10)) || 0; + + // Determine new dimension size based on max/min/current values + width = max + min ? Math.min(Math.max(width, min), max) : width; + + // Set the newly calculated width and remvoe fluid class + tooltip.css('width', Math.round(width)).removeClass(fluidClass); + } + + // Set drawing flag + isDrawing = 0; + + return self; + }, + + disable: function(state) + { + if('boolean' !== typeof state) { + state = !(tooltip.hasClass(disabled) || cache.disabled); + } + + if(self.rendered) { + tooltip.toggleClass(disabled, state); + $.attr(tooltip[0], 'aria-disabled', state); + } + else { + cache.disabled = !!state; + } + + return self; + }, + + enable: function() { return self.disable(FALSE); }, + + destroy: function() + { + var t = target[0], + title = $.attr(t, oldtitle), + elemAPI = target.data('qtip'); + + // Destroy tooltip and any associated plugins if rendered + if(self.rendered) { + tooltip.stop(1,0).remove(); + + $.each(self.plugins, function() { + if(this.destroy) { this.destroy(); } + }); + } + + // Clear timers and remove bound events + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + unassignEvents(); + + // If the API if actually this qTip API... + if(!elemAPI || self === elemAPI) { + // Remove api object + $.removeData(t, 'qtip'); + + // Reset old title attribute if removed + if(options.suppress && title) { + $.attr(t, 'title', title); + target.removeAttr(oldtitle); + } + + // Remove ARIA attributes + target.removeAttr('aria-describedby'); + } + + // Remove qTip events associated with this API + target.unbind('.qtip-'+id); + + // Remove ID from sued id object + delete usedIDs[self.id]; + + return target; + } + }); +} + +// Initialization method +function init(id, opts) +{ + var obj, posOptions, attr, config, title, + + // Setup element references + elem = $(this), + docBody = $(document.body), + + // Use document body instead of document element if needed + newTarget = this === document ? docBody : elem, + + // Grab metadata from element if plugin is present + metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL, + + // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise + metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL, + + // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method, + html5 = elem.data(opts.metadata.name || 'qtipopts'); + + // If we don't get an object returned attempt to parse it manualyl without parseJSON + try { html5 = typeof html5 === 'string' ? (new Function("return " + html5))() : html5; } + catch(e) { log('Unable to parse HTML5 attribute data: ' + html5); } + + // Merge in and sanitize metadata + config = $.extend(TRUE, {}, QTIP.defaults, opts, + typeof html5 === 'object' ? sanitizeOptions(html5) : NULL, + sanitizeOptions(metadata5 || metadata)); + + // Re-grab our positioning options now we've merged our metadata and set id to passed value + posOptions = config.position; + config.id = id; + + // Setup missing content if none is detected + if('boolean' === typeof config.content.text) { + attr = elem.attr(config.content.attr); + + // Grab from supplied attribute if available + if(config.content.attr !== FALSE && attr) { config.content.text = attr; } + + // No valid content was found, abort render + else { + log('Unable to locate content for tooltip! Aborting render of tooltip on element: ', elem); + return FALSE; + } + } + + // Setup target options + if(!posOptions.container.length) { posOptions.container = docBody; } + if(posOptions.target === FALSE) { posOptions.target = newTarget; } + if(config.show.target === FALSE) { config.show.target = newTarget; } + if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); } + if(config.hide.target === FALSE) { config.hide.target = newTarget; } + if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; } + + // Ensure we only use a single container + posOptions.container = posOptions.container.eq(0); + + // Convert position corner values into x and y strings + posOptions.at = new PLUGINS.Corner(posOptions.at); + posOptions.my = new PLUGINS.Corner(posOptions.my); + + // Destroy previous tooltip if overwrite is enabled, or skip element if not + if($.data(this, 'qtip')) { + if(config.overwrite) { + elem.qtip('destroy'); + } + else if(config.overwrite === FALSE) { + return FALSE; + } + } + + // Remove title attribute and store it if present + if(config.suppress && (title = $.attr(this, 'title'))) { + $(this).removeAttr('title').attr(oldtitle, title); + } + + // Initialize the tooltip and add API reference + obj = new QTip(elem, config, id, !!attr); + $.data(this, 'qtip', obj); + + // Catch remove/removeqtip events on target element to destroy redundant tooltip + elem.bind('remove.qtip-'+id+' removeqtip.qtip-'+id, function(){ obj.destroy(); }); + + return obj; +} + +// jQuery $.fn extension method +QTIP = $.fn.qtip = function(options, notation, newValue) +{ + var command = ('' + options).toLowerCase(), // Parse command + returned = NULL, + args = $.makeArray(arguments).slice(1), + event = args[args.length - 1], + opts = this[0] ? $.data(this[0], 'qtip') : NULL; + + // Check for API request + if((!arguments.length && opts) || command === 'api') { + return opts; + } + + // Execute API command if present + else if('string' === typeof options) + { + this.each(function() + { + var api = $.data(this, 'qtip'); + if(!api) { return TRUE; } + + // Cache the event if possible + if(event && event.timeStamp) { api.cache.event = event; } + + // Check for specific API commands + if((command === 'option' || command === 'options') && notation) { + if($.isPlainObject(notation) || newValue !== undefined) { + api.set(notation, newValue); + } + else { + returned = api.get(notation); + return FALSE; + } + } + + // Execute API command + else if(api[command]) { + api[command].apply(api[command], args); + } + }); + + return returned !== NULL ? returned : this; + } + + // No API commands. validate provided options and setup qTips + else if('object' === typeof options || !arguments.length) + { + opts = sanitizeOptions($.extend(TRUE, {}, options)); + + // Bind the qTips + return QTIP.bind.call(this, opts, event); + } +}; + +// $.fn.qtip Bind method +QTIP.bind = function(opts, event) +{ + return this.each(function(i) { + var options, targets, events, namespace, api, id; + + // Find next available ID, or use custom ID if provided + id = $.isArray(opts.id) ? opts.id[i] : opts.id; + id = !id || id === FALSE || id.length < 1 || usedIDs[id] ? QTIP.nextid++ : (usedIDs[id] = id); + + // Setup events namespace + namespace = '.qtip-'+id+'-create'; + + // Initialize the qTip and re-grab newly sanitized options + api = init.call(this, id, opts); + if(api === FALSE) { return TRUE; } + options = api.options; + + // Initialize plugins + $.each(PLUGINS, function() { + if(this.initialize === 'initialize') { this(api); } + }); + + // Determine hide and show targets + targets = { show: options.show.target, hide: options.hide.target }; + events = { + show: $.trim('' + options.show.event).replace(/ /g, namespace+' ') + namespace, + hide: $.trim('' + options.hide.event).replace(/ /g, namespace+' ') + namespace + }; + + /* + * Make sure hoverIntent functions properly by using mouseleave as a hide event if + * mouseenter/mouseout is used for show.event, even if it isn't in the users options. + */ + if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) { + events.hide += ' mouseleave' + namespace; + } + + /* + * Also make sure initial mouse targetting works correctly by caching mousemove coords + * on show targets before the tooltip has rendered. + * + * Also set onTarget when triggered to keep mouse tracking working + */ + targets.show.bind('mousemove'+namespace, function(event) { + MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' }; + api.cache.onTarget = TRUE; + }); + + // Define hoverIntent function + function hoverIntent(event) { + function render() { + // Cache mouse coords,render and render the tooltip + api.render(typeof event === 'object' || options.show.ready); + + // Unbind show and hide events + targets.show.add(targets.hide).unbind(namespace); + } + + // Only continue if tooltip isn't disabled + if(api.cache.disabled) { return FALSE; } + + // Cache the event data + api.cache.event = $.extend({}, event); + api.cache.target = event ? $(event.target) : [undefined]; + + // Start the event sequence + if(options.show.delay > 0) { + clearTimeout(api.timers.show); + api.timers.show = setTimeout(render, options.show.delay); + if(events.show !== events.hide) { + targets.hide.bind(events.hide, function() { clearTimeout(api.timers.show); }); + } + } + else { render(); } + } + + // Bind show events to target + targets.show.bind(events.show, hoverIntent); + + // Prerendering is enabled, create tooltip now + if(options.show.ready || options.prerender) { hoverIntent(event); } + }); +}; + +// Setup base plugins +PLUGINS = QTIP.plugins = { + // Corner object parser + Corner: function(corner) { + corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, 'center').toLowerCase(); + this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase(); + this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase(); + + var f = corner.charAt(0); this.precedance = (f === 't' || f === 'b' ? 'y' : 'x'); + + this.string = function() { return this.precedance === 'y' ? this.y+this.x : this.x+this.y; }; + this.abbrev = function() { + var x = this.x.substr(0,1), y = this.y.substr(0,1); + return x === y ? x : (x === 'c' || (x !== 'c' && y !== 'c')) ? y + x : x + y; + }; + + this.clone = function() { + return { x: this.x, y: this.y, precedance: this.precedance, string: this.string, abbrev: this.abbrev, clone: this.clone }; + }; + }, + + // Custom (more correct for qTip!) offset calculator + offset: function(elem, container) { + var pos = elem.offset(), + docBody = elem.closest('body')[0], + parent = container, scrolled, + coffset, overflow; + + function scroll(e, i) { + pos.left += i * e.scrollLeft(); + pos.top += i * e.scrollTop(); + } + + if(parent) { + // Compensate for non-static containers offset + do { + if(parent.css('position') !== 'static') { + coffset = parent.position(); + + // Account for element positioning, borders and margins + pos.left -= coffset.left + (parseInt(parent.css('borderLeftWidth'), 10) || 0) + (parseInt(parent.css('marginLeft'), 10) || 0); + pos.top -= coffset.top + (parseInt(parent.css('borderTopWidth'), 10) || 0) + (parseInt(parent.css('marginTop'), 10) || 0); + + // If this is the first parent element with an overflow of "scroll" or "auto", store it + if(!scrolled && (overflow = parent.css('overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = parent; } + } + } + while((parent = $(parent[0].offsetParent)).length); + + // Compensate for containers scroll if it also has an offsetParent + if(scrolled && scrolled[0] !== docBody) { scroll( scrolled, 1 ); } + } + + return pos; + }, + + /* + * iOS 3.2 - 4.0 scroll fix detection used in offset() function. + */ + iOS: parseFloat( + ('' + (/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1]) + .replace('undefined', '3_2').replace('_','.') + ) || FALSE, + + /* + * jQuery-specific $.fn overrides + */ + fn: { + /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */ + attr: function(attr, val) { + if(this.length) { + var self = this[0], + title = 'title', + api = $.data(self, 'qtip'); + + if(attr === title && api && 'object' === typeof api && api.options.suppress) { + if(arguments.length < 2) { + return $.attr(self, oldtitle); + } + else { + // If qTip is rendered and title was originally used as content, update it + if(api && api.options.content.attr === title && api.cache.attr) { + api.set('content.text', val); + } + + // Use the regular attr method to set, then cache the result + return this.attr(oldtitle, val); + } + } + } + + return $.fn['attr'+replaceSuffix].apply(this, arguments); + }, + + /* Allow clone to correctly retrieve cached title attributes */ + clone: function(keepData) { + var titles = $([]), title = 'title', + + // Clone our element using the real clone method + elems = $.fn['clone'+replaceSuffix].apply(this, arguments); + + // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false + if(!keepData) { + elems.filter('['+oldtitle+']').attr('title', function() { + return $.attr(this, oldtitle); + }) + .removeAttr(oldtitle); + } + + return elems; + } + } +}; + +// Apply the fn overrides above +$.each(PLUGINS.fn, function(name, func) { + if(!func || $.fn[name+replaceSuffix]) { return TRUE; } + + var old = $.fn[name+replaceSuffix] = $.fn[name]; + $.fn[name] = function() { + return func.apply(this, arguments) || old.apply(this, arguments); + }; +}); + +/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar). + * This snippet is taken directly from jQuery UI source code found here: + * http://code.jquery.com/ui/jquery-ui-git.js + */ +if(!$.ui) { + $['cleanData'+replaceSuffix] = $.cleanData; + $.cleanData = function( elems ) { + for(var i = 0, elem; (elem = elems[i]) !== undefined; i++) { + try { $( elem ).triggerHandler('removeqtip'); } + catch( e ) {} + } + $['cleanData'+replaceSuffix]( elems ); + }; +} + +// Set global qTip properties +QTIP.version = 'nightly'; +QTIP.nextid = 0; +QTIP.inactiveEvents = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '); +QTIP.zindex = 15000; + +// Define configuration defaults +QTIP.defaults = { + prerender: FALSE, + id: FALSE, + overwrite: TRUE, + suppress: TRUE, + content: { + text: TRUE, + attr: 'title', + title: { + text: FALSE, + button: FALSE + } + }, + position: { + my: 'top left', + at: 'bottom right', + target: FALSE, + container: FALSE, + viewport: FALSE, + adjust: { + x: 0, y: 0, + mouse: TRUE, + resize: TRUE, + method: 'flip flip' + }, + effect: function(api, pos, viewport) { + $(this).animate(pos, { + duration: 200, + queue: FALSE + }); + } + }, + show: { + target: FALSE, + event: 'mouseenter', + effect: TRUE, + delay: 90, + solo: FALSE, + ready: FALSE, + autofocus: FALSE + }, + hide: { + target: FALSE, + event: 'mouseleave', + effect: TRUE, + delay: 0, + fixed: FALSE, + inactive: FALSE, + leave: 'window', + distance: FALSE + }, + style: { + classes: '', + widget: FALSE, + width: FALSE, + height: FALSE, + def: TRUE + }, + events: { + render: NULL, + move: NULL, + show: NULL, + hide: NULL, + toggle: NULL, + visible: NULL, + hidden: NULL, + focus: NULL, + blur: NULL + } +}; + +function Ajax(api) +{ + var self = this, + tooltip = api.elements.tooltip, + opts = api.options.content.ajax, + namespace = '.qtip-ajax', + rscript = /)<[^<]*)*<\/script>/gi, + first = TRUE, + destroyed = FALSE, + xhr; + + api.checks.ajax = { + '^content.ajax': function(obj, name, v) { + // If content.ajax object was reset, set our local var + if(name === 'ajax') { opts = v; } + + if(name === 'once') { + self.init(); + } + else if(opts && opts.url) { + self.load(); + } + else { + tooltip.unbind(namespace); + } + } + }; + + $.extend(self, { + init: function() { + // Make sure ajax options are enabled and bind event + if(opts && opts.url) { + tooltip.unbind(namespace)[ opts.once ? 'one' : 'bind' ]('tooltipshow'+namespace, self.load); + } + + return self; + }, + + load: function(event, first) { + var hasSelector = opts.url.indexOf(' '), + url = opts.url, + selector, + hideFirst = opts.once && !opts.loading && first; + + // If loading option is disabled, prevent the tooltip showing until we've completed the request + if(hideFirst) { try{ event.preventDefault(); } catch(e) {} } + + // Make sure default event hasn't been prevented + else if(event && event.isDefaultPrevented()) { return self; } + + // Cancel old request + if(xhr && xhr.abort) { xhr.abort(); } + + // Check if user delcared a content selector like in .load() + if(hasSelector > -1) { + selector = url.substr(hasSelector); + url = url.substr(0, hasSelector); + } + + // Define common after callback for both success/error handlers + function after() { + if(destroyed) { return; } + + // Re-display tip if loading and first time, and reset first flag + if(hideFirst) { api.show(event.originalEvent); first = FALSE; } + + // Call users complete if it was defined + if($.isFunction(opts.complete)) { opts.complete.apply(this, arguments); } + } + + // Define success handler + function successHandler(content) { + if(destroyed) { return; } + + if(selector) { + // Create a dummy div to hold the results and grab the selector element + content = $('
    ') + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(content.replace(rscript, "")) + + // Locate the specified elements + .find(selector); + } + + // Set the content + api.set('content.text', content); + } + + // Error handler + function errorHandler(xhr, status, error) { + if (destroyed || xhr.status === 0) { return; } + api.set('content.text', status + ': ' + error); + } + + // Setup $.ajax option object and process the request + xhr = $.ajax( $.extend({ success: successHandler, error: errorHandler, context: api }, opts, { url: url, complete: after }) ); + }, + + destroy: function() { + // Cancel ajax request if possible + if(xhr && xhr.abort) { xhr.abort(); } + + // Set destroyed flag + destroyed = TRUE; + } + }); + + self.init(); +} + + +PLUGINS.ajax = function(api) +{ + var self = api.plugins.ajax; + + return 'object' === typeof self ? self : (api.plugins.ajax = new Ajax(api)); +}; + +PLUGINS.ajax.initialize = 'render'; + +// Setup plugin sanitization +PLUGINS.ajax.sanitize = function(options) +{ + var content = options.content, opts; + if(content && 'ajax' in content) { + opts = content.ajax; + if(typeof opts !== 'object') { opts = options.content.ajax = { url: opts }; } + if('boolean' !== typeof opts.once && opts.once) { opts.once = !!opts.once; } + } +}; + +// Extend original api defaults +$.extend(TRUE, QTIP.defaults, { + content: { + ajax: { + loading: TRUE, + once: TRUE + } + } +}); + +PLUGINS.imagemap = function(area, corner, flip) +{ + if(!area.jquery) { area = $(area); } + + var shape = (area[0].shape || area.attr('shape')).toLowerCase(), + baseCoords = (area[0].coords || area.attr('coords')).split(','), + coords = [], + image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'), + imageOffset = image.offset(), + result = { + width: 0, height: 0, + offset: { top: 1e10, right: 0, bottom: 0, left: 1e10 } + }, + i = 0, next = 0, dimensions; + + // POLY area coordinate calculator + // Special thanks to Ed Cradock for helping out with this. + // Uses a binary search algorithm to find suitable coordinates. + function polyCoordinates(result, coords, corner) + { + var i = 0, + compareX = 1, compareY = 1, + realX = 0, realY = 0, + newWidth = result.width, + newHeight = result.height; + + // Use a binary search algorithm to locate most suitable coordinate (hopefully) + while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0) + { + newWidth = Math.floor(newWidth / 2); + newHeight = Math.floor(newHeight / 2); + + if(corner.x === 'left'){ compareX = newWidth; } + else if(corner.x === 'right'){ compareX = result.width - newWidth; } + else{ compareX += Math.floor(newWidth / 2); } + + if(corner.y === 'top'){ compareY = newHeight; } + else if(corner.y === 'bottom'){ compareY = result.height - newHeight; } + else{ compareY += Math.floor(newHeight / 2); } + + i = coords.length; while(i--) + { + if(coords.length < 2){ break; } + + realX = coords[i][0] - result.offset.left; + realY = coords[i][1] - result.offset.top; + + if((corner.x === 'left' && realX >= compareX) || + (corner.x === 'right' && realX <= compareX) || + (corner.x === 'center' && (realX < compareX || realX > (result.width - compareX))) || + (corner.y === 'top' && realY >= compareY) || + (corner.y === 'bottom' && realY <= compareY) || + (corner.y === 'center' && (realY < compareY || realY > (result.height - compareY)))) { + coords.splice(i, 1); + } + } + } + + return { left: coords[0][0], top: coords[0][1] }; + } + + // Make sure we account for padding and borders on the image + imageOffset.left += Math.ceil((image.outerWidth() - image.width()) / 2); + imageOffset.top += Math.ceil((image.outerHeight() - image.height()) / 2); + + // Parse coordinates into proper array + if(shape === 'poly') { + i = baseCoords.length; while(i--) + { + next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ]; + + if(next[0] > result.offset.right){ result.offset.right = next[0]; } + if(next[0] < result.offset.left){ result.offset.left = next[0]; } + if(next[1] > result.offset.bottom){ result.offset.bottom = next[1]; } + if(next[1] < result.offset.top){ result.offset.top = next[1]; } + + coords.push(next); + } + } + else { + coords = $.map(baseCoords, function(coord){ return parseInt(coord, 10); }); + } + + // Calculate details + switch(shape) + { + case 'rect': + result = { + width: Math.abs(coords[2] - coords[0]), + height: Math.abs(coords[3] - coords[1]), + offset: { + left: Math.min(coords[0], coords[2]), + top: Math.min(coords[1], coords[3]) + } + }; + break; + + case 'circle': + result = { + width: coords[2] + 2, + height: coords[2] + 2, + offset: { left: coords[0], top: coords[1] } + }; + break; + + case 'poly': + $.extend(result, { + width: Math.abs(result.offset.right - result.offset.left), + height: Math.abs(result.offset.bottom - result.offset.top) + }); + + if(corner.string() === 'centercenter') { + result.offset = { + left: result.offset.left + (result.width / 2), + top: result.offset.top + (result.height / 2) + }; + } + else { + result.offset = polyCoordinates(result, coords.slice(), corner); + + // If flip adjustment is enabled, also calculate the closest opposite point + if(flip && (flip[0] === 'flip' || flip[1] === 'flip')) { + result.flipoffset = polyCoordinates(result, coords.slice(), { + x: corner.x === 'left' ? 'right' : corner.x === 'right' ? 'left' : 'center', + y: corner.y === 'top' ? 'bottom' : corner.y === 'bottom' ? 'top' : 'center' + }); + + result.flipoffset.left -= result.offset.left; + result.flipoffset.top -= result.offset.top; + } + } + + result.width = result.height = 0; + break; + } + + // Add image position to offset coordinates + result.offset.left += imageOffset.left; + result.offset.top += imageOffset.top; + + return result; +}; + +// Tip coordinates calculator +function calculateTip(corner, width, height) +{ + var width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2), + + // Define tip coordinates in terms of height and width values + tips = { + bottomright: [[0,0], [width,height], [width,0]], + bottomleft: [[0,0], [width,0], [0,height]], + topright: [[0,height], [width,0], [width,height]], + topleft: [[0,0], [0,height], [width,height]], + topcenter: [[0,height], [width2,0], [width,height]], + bottomcenter: [[0,0], [width,0], [width2,height]], + rightcenter: [[0,0], [width,height2], [0,height]], + leftcenter: [[width,0], [width,height], [0,height2]] + }; + + // Set common side shapes + tips.lefttop = tips.bottomright; tips.righttop = tips.bottomleft; + tips.leftbottom = tips.topright; tips.rightbottom = tips.topleft; + + return tips[ corner.string() ]; +} + + +function Tip(qTip, command) +{ + var self = this, + opts = qTip.options.style.tip, + elems = qTip.elements, + tooltip = elems.tooltip, + cache = { top: 0, left: 0 }, + size = { + width: opts.width, + height: opts.height + }, + color = { }, + border = opts.border || 0, + namespace = '.qtip-tip', + hasCanvas = !!($('')[0] || {}).getContext; + + self.corner = NULL; + self.mimic = NULL; + self.border = border; + self.offset = opts.offset; + self.size = size; + + // Add new option checks for the plugin + qTip.checks.tip = { + '^position.my|style.tip.(corner|mimic|border)$': function() { + // Make sure a tip can be drawn + if(!self.init()) { + self.destroy(); + } + + // Reposition the tooltip + qTip.reposition(); + }, + '^style.tip.(height|width)$': function() { + // Re-set dimensions and redraw the tip + size = { + width: opts.width, + height: opts.height + }; + self.create(); + self.update(); + + // Reposition the tooltip + qTip.reposition(); + }, + '^content.title.text|style.(classes|widget)$': function() { + if(elems.tip) { + self.update(); + } + } + }; + + function reposition(event, api, pos, viewport) { + if(!elems.tip) { return; } + + var newCorner = self.corner.clone(), + adjust = pos.adjusted, + method = qTip.options.position.adjust.method.split(' '), + horizontal = method[0], + vertical = method[1] || method[0], + shift = { left: FALSE, top: FALSE, x: 0, y: 0 }, + offset, css = {}, props; + + // Make sure our tip position isn't fixed e.g. doesn't adjust with viewport + if(self.corner.fixed !== TRUE) { + // Horizontal - Shift or flip method + if(horizontal === 'shift' && newCorner.precedance === 'x' && adjust.left && newCorner.y !== 'center') { + newCorner.precedance = newCorner.precedance === 'x' ? 'y' : 'x'; + } + else if(horizontal === 'flip' && adjust.left){ + newCorner.x = newCorner.x === 'center' ? (adjust.left > 0 ? 'left' : 'right') : (newCorner.x === 'left' ? 'right' : 'left'); + } + + // Vertical - Shift or flip method + if(vertical === 'shift' && newCorner.precedance === 'y' && adjust.top && newCorner.x !== 'center') { + newCorner.precedance = newCorner.precedance === 'y' ? 'x' : 'y'; + } + else if(vertical === 'flip' && adjust.top) { + newCorner.y = newCorner.y === 'center' ? (adjust.top > 0 ? 'top' : 'bottom') : (newCorner.y === 'top' ? 'bottom' : 'top'); + } + + // Update and redraw the tip if needed (check cached details of last drawn tip) + if(newCorner.string() !== cache.corner.string() && (cache.top !== adjust.top || cache.left !== adjust.left)) { + self.update(newCorner, FALSE); + } + } + + // Setup tip offset properties + offset = self.position(newCorner, adjust); + if(offset.right !== undefined) { offset.left = -offset.right; } + if(offset.bottom !== undefined) { offset.top = -offset.bottom; } + offset.user = Math.max(0, opts.offset); + + // Viewport "shift" specific adjustments + if(shift.left = (horizontal === 'shift' && !!adjust.left)) { + if(newCorner.x === 'center') { + css['margin-left'] = shift.x = offset['margin-left'] - adjust.left; + } + else { + props = offset.right !== undefined ? + [ adjust.left, -offset.left ] : [ -adjust.left, offset.left ]; + + if( (shift.x = Math.max(props[0], props[1])) > props[0] ) { + pos.left -= adjust.left; + shift.left = FALSE; + } + + css[ offset.right !== undefined ? 'right' : 'left' ] = shift.x; + } + } + if(shift.top = (vertical === 'shift' && !!adjust.top)) { + if(newCorner.y === 'center') { + css['margin-top'] = shift.y = offset['margin-top'] - adjust.top; + } + else { + props = offset.bottom !== undefined ? + [ adjust.top, -offset.top ] : [ -adjust.top, offset.top ]; + + if( (shift.y = Math.max(props[0], props[1])) > props[0] ) { + pos.top -= adjust.top; + shift.top = FALSE; + } + + css[ offset.bottom !== undefined ? 'bottom' : 'top' ] = shift.y; + } + } + + /* + * If the tip is adjusted in both dimensions, or in a + * direction that would cause it to be anywhere but the + * outer border, hide it! + */ + elems.tip.css(css).toggle( + !((shift.x && shift.y) || (newCorner.x === 'center' && shift.y) || (newCorner.y === 'center' && shift.x)) + ); + + // Adjust position to accomodate tip dimensions + pos.left -= offset.left.charAt ? offset.user : horizontal !== 'shift' || shift.top || !shift.left && !shift.top ? offset.left : 0; + pos.top -= offset.top.charAt ? offset.user : vertical !== 'shift' || shift.left || !shift.left && !shift.top ? offset.top : 0; + + // Cache details + cache.left = adjust.left; cache.top = adjust.top; + cache.corner = newCorner.clone(); + } + + /* border width calculator */ + function borderWidth(corner, side, backup) { + side = !side ? corner[corner.precedance] : side; + + var isFluid = tooltip.hasClass(fluidClass), + isTitleTop = elems.titlebar && corner.y === 'top', + elem = isTitleTop ? elems.titlebar : elems.content, + css = 'border-' + side + '-width', + val; + + // Grab the border-width value (add fluid class if needed) + tooltip.addClass(fluidClass); + val = parseInt(elem.css(css), 10); + val = (backup ? val || parseInt(tooltip.css(css), 10) : val) || 0; + tooltip.toggleClass(fluidClass, isFluid); + + return val; + } + + function borderRadius(corner) { + var isTitleTop = elems.titlebar && corner.y === 'top', + elem = isTitleTop ? elems.titlebar : elems.content, + moz = $.browser.mozilla, + prefix = moz ? '-moz-' : $.browser.webkit ? '-webkit-' : '', + side = corner.y + (moz ? '' : '-') + corner.x, + css = prefix + (moz ? 'border-radius-' + side : 'border-' + side + '-radius'); + + return parseInt(elem.css(css), 10) || parseInt(tooltip.css(css), 10) || 0; + } + + function calculateSize(corner) { + var y = corner.precedance === 'y', + width = size [ y ? 'width' : 'height' ], + height = size [ y ? 'height' : 'width' ], + isCenter = corner.string().indexOf('center') > -1, + base = width * (isCenter ? 0.5 : 1), + pow = Math.pow, + round = Math.round, + bigHyp, ratio, result, + + smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ), + + hyp = [ + (border / base) * smallHyp, (border / height) * smallHyp + ]; + hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(border, 2) ); + hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(border, 2) ); + + bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]); + ratio = bigHyp / smallHyp; + + result = [ round(ratio * height), round(ratio * width) ]; + return { height: result[ y ? 0 : 1 ], width: result[ y ? 1 : 0 ] }; + } + + $.extend(self, { + init: function() + { + var enabled = self.detectCorner() && (hasCanvas || $.browser.msie); + + // Determine tip corner and type + if(enabled) { + // Create a new tip and draw it + self.create(); + self.update(); + + // Bind update events + tooltip.unbind(namespace).bind('tooltipmove'+namespace, reposition); + } + + return enabled; + }, + + detectCorner: function() + { + var corner = opts.corner, + posOptions = qTip.options.position, + at = posOptions.at, + my = posOptions.my.string ? posOptions.my.string() : posOptions.my; + + // Detect corner and mimic properties + if(corner === FALSE || (my === FALSE && at === FALSE)) { + return FALSE; + } + else { + if(corner === TRUE) { + self.corner = new PLUGINS.Corner(my); + } + else if(!corner.string) { + self.corner = new PLUGINS.Corner(corner); + self.corner.fixed = TRUE; + } + } + + // Cache it + cache.corner = new PLUGINS.Corner( self.corner.string() ); + + return self.corner.string() !== 'centercenter'; + }, + + detectColours: function(actual) { + var i, fill, border, + tip = elems.tip.css('cssText', ''), + corner = actual || self.corner, + precedance = corner[ corner.precedance ], + + borderSide = 'border-' + precedance + '-color', + borderSideCamel = 'border' + precedance.charAt(0) + precedance.substr(1) + 'Color', + + invalid = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i, + backgroundColor = 'background-color', + transparent = 'transparent', + important = ' !important', + + bodyBorder = $(document.body).css('color'), + contentColour = qTip.elements.content.css('color'), + + useTitle = elems.titlebar && (corner.y === 'top' || (corner.y === 'center' && tip.position().top + (size.height / 2) + opts.offset < elems.titlebar.outerHeight(1))), + colorElem = useTitle ? elems.titlebar : elems.content; + + // Apply the fluid class so we can see our CSS values properly + tooltip.addClass(fluidClass); + + // Detect tip colours from CSS styles + color.fill = fill = tip.css(backgroundColor); + color.border = border = tip[0].style[ borderSideCamel ] || tip.css(borderSide) || tooltip.css(borderSide); + + // Make sure colours are valid + if(!fill || invalid.test(fill)) { + color.fill = colorElem.css(backgroundColor) || transparent; + if(invalid.test(color.fill)) { + color.fill = tooltip.css(backgroundColor) || fill; + } + } + if(!border || invalid.test(border) || border === bodyBorder) { + color.border = colorElem.css(borderSide) || transparent; + if(invalid.test(color.border)) { + color.border = border; + } + } + + // Reset background and border colours + $('*', tip).add(tip).css('cssText', backgroundColor+':'+transparent+important+';border:0'+important+';'); + + // Remove fluid class + tooltip.removeClass(fluidClass); + }, + + create: function() + { + var width = size.width, + height = size.height, + vml; + + // Remove previous tip element if present + if(elems.tip) { elems.tip.remove(); } + + // Create tip element and prepend to the tooltip + elems.tip = $('
    ', { 'class': 'ui-tooltip-tip' }).css({ width: width, height: height }).prependTo(tooltip); + + // Create tip drawing element(s) + if(hasCanvas) { + // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()! + $('').appendTo(elems.tip)[0].getContext('2d').save(); + } + else { + vml = ''; + elems.tip.html(vml + vml); + + // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML + $('*', elems.tip).bind('click mousedown', function(event) { event.stopPropagation(); }); + } + }, + + update: function(corner, position) + { + var tip = elems.tip, + inner = tip.children(), + width = size.width, + height = size.height, + regular = 'px solid ', + transparent = 'px dashed transparent', // Dashed IE6 border-transparency hack. Awesome! + mimic = opts.mimic, + round = Math.round, + precedance, context, coords, translate, newSize; + + // Re-determine tip if not already set + if(!corner) { corner = cache.corner || self.corner; } + + // Use corner property if we detect an invalid mimic value + if(mimic === FALSE) { mimic = corner; } + + // Otherwise inherit mimic properties from the corner object as necessary + else { + mimic = new PLUGINS.Corner(mimic); + mimic.precedance = corner.precedance; + + if(mimic.x === 'inherit') { mimic.x = corner.x; } + else if(mimic.y === 'inherit') { mimic.y = corner.y; } + else if(mimic.x === mimic.y) { + mimic[ corner.precedance ] = corner[ corner.precedance ]; + } + } + precedance = mimic.precedance; + + // Update our colours + self.detectColours(corner); + + // Detect border width, taking into account colours + if(color.border !== 'transparent' && color.border !== '#123456') { + // Grab border width + border = borderWidth(corner, NULL, TRUE); + + // If border width isn't zero, use border color as fill (1.0 style tips) + if(opts.border === 0 && border > 0) { color.fill = color.border; } + + // Set border width (use detected border width if opts.border is true) + self.border = border = opts.border !== TRUE ? opts.border : border; + } + + // Border colour was invalid, set border to zero + else { self.border = border = 0; } + + // Calculate coordinates + coords = calculateTip(mimic, width , height); + + // Determine tip size + self.size = newSize = calculateSize(corner); + tip.css(newSize); + + // Calculate tip translation + if(corner.precedance === 'y') { + translate = [ + round(mimic.x === 'left' ? border : mimic.x === 'right' ? newSize.width - width - border : (newSize.width - width) / 2), + round(mimic.y === 'top' ? newSize.height - height : 0) + ]; + } + else { + translate = [ + round(mimic.x === 'left' ? newSize.width - width : 0), + round(mimic.y === 'top' ? border : mimic.y === 'bottom' ? newSize.height - height - border : (newSize.height - height) / 2) + ]; + } + + // Canvas drawing implementation + if(hasCanvas) { + // Set the canvas size using calculated size + inner.attr(newSize); + + // Grab canvas context and clear/save it + context = inner[0].getContext('2d'); + context.restore(); context.save(); + context.clearRect(0,0,3000,3000); + + // Translate origin + context.translate(translate[0], translate[1]); + + // Draw the tip + context.beginPath(); + context.moveTo(coords[0][0], coords[0][1]); + context.lineTo(coords[1][0], coords[1][1]); + context.lineTo(coords[2][0], coords[2][1]); + context.closePath(); + context.fillStyle = color.fill; + context.strokeStyle = color.border; + context.lineWidth = border * 2; + context.lineJoin = 'miter'; + context.miterLimit = 100; + if(border) { context.stroke(); } + context.fill(); + } + + // VML (IE Proprietary implementation) + else { + // Setup coordinates string + coords = 'm' + coords[0][0] + ',' + coords[0][1] + ' l' + coords[1][0] + + ',' + coords[1][1] + ' ' + coords[2][0] + ',' + coords[2][1] + ' xe'; + + // Setup VML-specific offset for pixel-perfection + translate[2] = border && /^(r|b)/i.test(corner.string()) ? + parseFloat($.browser.version, 10) === 8 ? 2 : 1 : 0; + + // Set initial CSS + inner.css({ + antialias: ''+(mimic.string().indexOf('center') > -1), + left: translate[0] - (translate[2] * Number(precedance === 'x')), + top: translate[1] - (translate[2] * Number(precedance === 'y')), + width: width + border, + height: height + border + }) + .each(function(i) { + var $this = $(this); + + // Set shape specific attributes + $this[ $this.prop ? 'prop' : 'attr' ]({ + coordsize: (width+border) + ' ' + (height+border), + path: coords, + fillcolor: color.fill, + filled: !!i, + stroked: !!!i + }) + .css({ display: border || i ? 'block' : 'none' }); + + // Check if border is enabled and add stroke element + if(!i && $this.html() === '') { + $this.html( + '' + ); + } + }); + } + + // Position if needed + if(position !== FALSE) { self.position(corner); } + }, + + // Tip positioning method + position: function(corner) + { + var tip = elems.tip, + position = {}, + userOffset = Math.max(0, opts.offset), + precedance, dimensions, corners; + + // Return if tips are disabled or tip is not yet rendered + if(opts.corner === FALSE || !tip) { return FALSE; } + + // Inherit corner if not provided + corner = corner || self.corner; + precedance = corner.precedance; + + // Determine which tip dimension to use for adjustment + dimensions = calculateSize(corner); + + // Setup corners and offset array + corners = [ corner.x, corner.y ]; + if(precedance === 'x') { corners.reverse(); } + + // Calculate tip position + $.each(corners, function(i, side) { + var b, br; + + if(side === 'center') { + b = precedance === 'y' ? 'left' : 'top'; + position[ b ] = '50%'; + position['margin-' + b] = -Math.round(dimensions[ precedance === 'y' ? 'width' : 'height' ] / 2) + userOffset; + } + else { + b = borderWidth(corner, side, TRUE); + br = borderRadius(corner); + + position[ side ] = i ? + border ? borderWidth(corner, side) : 0 : + userOffset + (br > b ? br : 0); + } + }); + + // Adjust for tip dimensions + position[ corner[precedance] ] -= dimensions[ precedance === 'x' ? 'width' : 'height' ]; + + // Set and return new position + tip.css({ top: '', bottom: '', left: '', right: '', margin: '' }).css(position); + return position; + }, + + destroy: function() + { + // Remov tip and bound events + if(elems.tip) { elems.tip.remove(); } + tooltip.unbind(namespace); + } + }); + + self.init(); +} + +PLUGINS.tip = function(api) +{ + var self = api.plugins.tip; + + return 'object' === typeof self ? self : (api.plugins.tip = new Tip(api)); +}; + +// Initialize tip on render +PLUGINS.tip.initialize = 'render'; + +// Setup plugin sanitization options +PLUGINS.tip.sanitize = function(options) +{ + var style = options.style, opts; + if(style && 'tip' in style) { + opts = options.style.tip; + if(typeof opts !== 'object'){ options.style.tip = { corner: opts }; } + if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; } + if(typeof opts.width !== 'number'){ delete opts.width; } + if(typeof opts.height !== 'number'){ delete opts.height; } + if(typeof opts.border !== 'number' && opts.border !== TRUE){ delete opts.border; } + if(typeof opts.offset !== 'number'){ delete opts.offset; } + } +}; + +// Extend original qTip defaults +$.extend(TRUE, QTIP.defaults, { + style: { + tip: { + corner: TRUE, + mimic: FALSE, + width: 6, + height: 6, + border: TRUE, + offset: 0 + } + } +}); + +PLUGINS.svg = function(svg, corner) +{ + var doc = $(document), + elem = svg[0], + result = { + width: 0, height: 0, + offset: { top: 1e10, left: 1e10 } + }, + box, mtx, root, point, tPoint; + + if (elem.getBBox && elem.parentNode) { + box = elem.getBBox(); + mtx = elem.getScreenCTM(); + root = elem.farthestViewportElement || elem; + + // Return if no method is found + if(!root.createSVGPoint) { return result; } + + // Create our point var + point = root.createSVGPoint(); + + // Adjust top and left + point.x = box.x; + point.y = box.y; + tPoint = point.matrixTransform(mtx); + result.offset.left = tPoint.x; + result.offset.top = tPoint.y; + + // Adjust width and height + point.x += box.width; + point.y += box.height; + tPoint = point.matrixTransform(mtx); + result.width = tPoint.x - result.offset.left; + result.height = tPoint.y - result.offset.top; + + // Adjust by scroll offset + result.offset.left += doc.scrollLeft(); + result.offset.top += doc.scrollTop(); + } + + return result; +}; + +function Modal(api) +{ + var self = this, + options = api.options.show.modal, + elems = api.elements, + tooltip = elems.tooltip, + overlaySelector = '#qtip-overlay', + globalNamespace = '.qtipmodal', + namespace = globalNamespace + api.id, + attr = 'is-modal-qtip', + docBody = $(document.body), + overlay; + + // Setup option set checks + api.checks.modal = { + '^show.modal.(on|blur)$': function() { + // Initialise + self.init(); + + // Show the modal if not visible already and tooltip is visible + elems.overlay.toggle( tooltip.is(':visible') ); + } + }; + + $.extend(self, { + init: function() + { + // If modal is disabled... return + if(!options.on) { return self; } + + // Create the overlay if needed + overlay = self.create(); + + // Add unique attribute so we can grab modal tooltips easily via a selector + tooltip.attr(attr, TRUE) + + // Set z-index + .css('z-index', PLUGINS.modal.zindex + $(selector+'['+attr+']').length) + + // Remove previous bound events in globalNamespace + .unbind(globalNamespace).unbind(namespace) + + // Apply our show/hide/focus modal events + .bind('tooltipshow'+globalNamespace+' tooltiphide'+globalNamespace, function(event, api, duration) { + var oEvent = event.originalEvent; + + // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop + if(event.target === tooltip[0]) { + if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(overlay[0]).length) { + try { event.preventDefault(); } catch(e) {} + } + else if(!oEvent || (oEvent && !oEvent.solo)) { + self[ event.type.replace('tooltip', '') ](event, duration); + } + } + }) + + // Adjust modal z-index on tooltip focus + .bind('tooltipfocus'+globalNamespace, function(event) { + // If focus was cancelled before it reearch us, don't do anything + if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; } + + var qtips = $(selector).filter('['+attr+']'), + + // Keep the modal's lower than other, regular qtips + newIndex = PLUGINS.modal.zindex + qtips.length, + curIndex = parseInt(tooltip[0].style.zIndex, 10); + + // Set overlay z-index + overlay[0].style.zIndex = newIndex - 1; + + // Reduce modal z-index's and keep them properly ordered + qtips.each(function() { + if(this.style.zIndex > curIndex) { + this.style.zIndex -= 1; + } + }); + + // Fire blur event for focused tooltip + qtips.end().filter('.' + focusClass).qtip('blur', event.originalEvent); + + // Set the new z-index + tooltip.addClass(focusClass)[0].style.zIndex = newIndex; + + // Prevent default handling + try { event.preventDefault(); } catch(e) {} + }) + + // Focus any other visible modals when this one hides + .bind('tooltiphide'+globalNamespace, function(event) { + if(event.target === tooltip[0]) { + $('[' + attr + ']').filter(':visible').not(tooltip).last().qtip('focus', event); + } + }); + + // Apply keyboard "Escape key" close handler + if(options.escape) { + $(window).unbind(namespace).bind('keydown'+namespace, function(event) { + if(event.keyCode === 27 && tooltip.hasClass(focusClass)) { + api.hide(event); + } + }); + } + + // Apply click handler for blur option + if(options.blur) { + elems.overlay.unbind(namespace).bind('click'+namespace, function(event) { + if(tooltip.hasClass(focusClass)) { api.hide(event); } + }); + } + + return self; + }, + + create: function() + { + var elem = $(overlaySelector); + + // Return if overlay is already rendered + if(elem.length) { + // Modal overlay should always be below all tooltips if possible + return (elems.overlay = elem.insertAfter( $(selector).last() )); + } + + // Create document overlay + overlay = elems.overlay = $('
    ', { + id: overlaySelector.substr(1), + html: '
    ', + mousedown: function() { return FALSE; } + }) + .insertAfter( $(selector).last() ); + + // Update position on window resize or scroll + function resize() { + overlay.css({ + height: $(window).height(), + width: $(window).width() + }); + } + $(window).unbind(globalNamespace).bind('resize'+globalNamespace, resize); + resize(); // Fire it initially too + + return overlay; + }, + + toggle: function(event, state, duration) + { + // Make sure default event hasn't been prevented + if(event && event.isDefaultPrevented()) { return self; } + + var effect = options.effect, + type = state ? 'show': 'hide', + visible = overlay.is(':visible'), + modals = $('[' + attr + ']').filter(':visible').not(tooltip), + zindex; + + // Create our overlay if it isn't present already + if(!overlay) { overlay = self.create(); } + + // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible + if((overlay.is(':animated') && visible === state) || (!state && modals.length)) { return self; } + + // State specific... + if(state) { + // Set position + overlay.css({ left: 0, top: 0 }); + + // Toggle backdrop cursor style on show + overlay.toggleClass('blurs', options.blur); + + // Make sure we can't focus anything outside the tooltip + docBody.bind('focusin'+namespace, function(event) { + var target = $(event.target), + container = target.closest('.qtip'), + + // Determine if input container target is above this + targetOnTop = container.length < 1 ? FALSE : + (parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10)); + + // If we're showing a modal, but focus has landed on an input below + // this modal, divert focus to the first visible input in this modal + if(!targetOnTop && ($(event.target).closest(selector)[0] !== tooltip[0])) { + tooltip.find('input:visible').filter(':first').focus(); + } + }); + } + else { + // Undelegate focus handler + docBody.undelegate('*', 'focusin'+namespace); + } + + // Stop all animations + overlay.stop(TRUE, FALSE); + + // Use custom function if provided + if($.isFunction(effect)) { + effect.call(overlay, state); + } + + // If no effect type is supplied, use a simple toggle + else if(effect === FALSE) { + overlay[ type ](); + } + + // Use basic fade function + else { + overlay.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() { + if(!state) { $(this).hide(); } + }); + } + + // Reset position on hide + if(!state) { + overlay.queue(function(next) { + overlay.css({ left: '', top: '' }); + next(); + }); + } + + return self; + }, + + show: function(event, duration) { return self.toggle(event, TRUE, duration); }, + hide: function(event, duration) { return self.toggle(event, FALSE, duration); }, + + destroy: function() + { + var delBlanket = overlay; + + if(delBlanket) { + // Check if any other modal tooltips are present + delBlanket = $('[' + attr + ']').not(tooltip).length < 1; + + // Remove overlay if needed + if(delBlanket) { + elems.overlay.remove(); + $(window).unbind(globalNamespace); + } + else { + elems.overlay.unbind(globalNamespace+api.id); + } + + // Undelegate focus handler + docBody.undelegate('*', 'focusin'+namespace); + } + + // Remove bound events + return tooltip.removeAttr(attr).unbind(globalNamespace); + } + }); + + self.init(); +} + +PLUGINS.modal = function(api) { + var self = api.plugins.modal; + + return 'object' === typeof self ? self : (api.plugins.modal = new Modal(api)); +}; + +// Plugin needs to be initialized on render +PLUGINS.modal.initialize = 'render'; + +// Setup sanitiztion rules +PLUGINS.modal.sanitize = function(opts) { + if(opts.show) { + if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; } + else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; } + } +}; + +// Base z-index for all modal tooltips (use qTip core z-index as a base) +PLUGINS.modal.zindex = QTIP.zindex + 1000; + +// Extend original api defaults +$.extend(TRUE, QTIP.defaults, { + show: { + modal: { + on: FALSE, + effect: TRUE, + blur: TRUE, + escape: TRUE + } + } +}); + +/* + * BGIFrame adaption (http://plugins.jquery.com/project/bgiframe) + * Special thanks to Brandon Aaron + */ +function BGIFrame(api) +{ + var self = this, + elems = api.elements, + tooltip = elems.tooltip, + namespace = '.bgiframe-' + api.id; + + $.extend(self, { + init: function() + { + // Create the BGIFrame element + elems.bgiframe = $(''); + + // Append the new element to the tooltip + elems.bgiframe.appendTo(tooltip); + + // Update BGIFrame on tooltip move + tooltip.bind('tooltipmove'+namespace, self.adjust); + }, + + adjust: function() + { + var dimensions = api.get('dimensions'), // Determine current tooltip dimensions + plugin = api.plugins.tip, + tip = elems.tip, + tipAdjust, offset; + + // Adjust border offset + offset = parseInt(tooltip.css('border-left-width'), 10) || 0; + offset = { left: -offset, top: -offset }; + + // Adjust for tips plugin + if(plugin && tip) { + tipAdjust = (plugin.corner.precedance === 'x') ? ['width', 'left'] : ['height', 'top']; + offset[ tipAdjust[1] ] -= tip[ tipAdjust[0] ](); + } + + // Update bgiframe + elems.bgiframe.css(offset).css(dimensions); + }, + + destroy: function() + { + // Remove iframe + elems.bgiframe.remove(); + + // Remove bound events + tooltip.unbind(namespace); + } + }); + + self.init(); +} + +PLUGINS.bgiframe = function(api) +{ + var browser = $.browser, + self = api.plugins.bgiframe; + + // Proceed only if the browser is IE6 and offending elements are present + if($('select, object').length < 1 || !(browser.msie && (''+browser.version).charAt(0) === '6')) { + return FALSE; + } + + return 'object' === typeof self ? self : (api.plugins.bgiframe = new BGIFrame(api)); +}; + +// Plugin needs to be initialized on render +PLUGINS.bgiframe.initialize = 'render'; + + +})); \ No newline at end of file diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.min.css b/www/themes/profind/lib/qtip2/jquery.qtip.min.css new file mode 100644 index 0000000..947c8f9 --- /dev/null +++ b/www/themes/profind/lib/qtip2/jquery.qtip.min.css @@ -0,0 +1 @@ +.ui-tooltip,.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;}.ui-tooltip-fluid{display:block;visibility:hidden;position:static!important;float:left!important;}.ui-tooltip-content{position:relative;padding:5px 9px;overflow:hidden;border:1px solid #000001;text-align:left;word-wrap:break-word;overflow:hidden;}.ui-tooltip-titlebar{position:relative;min-height:14px;padding:5px 35px 5px 10px;overflow:hidden;border:1px solid #000001;border-width:1px 1px 0;font-weight:bold;}.ui-tooltip-titlebar+.ui-tooltip-content{border-top-width:0!important;}/*!Default close button class */ .ui-tooltip-titlebar .ui-state-default{position:absolute;right:4px;top:50%;margin-top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;}* html .ui-tooltip-titlebar .ui-state-default{top:16px;}.ui-tooltip-titlebar .ui-icon,.ui-tooltip-icon .ui-icon{display:block;text-indent:-1000em;}.ui-tooltip-icon,.ui-tooltip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;}.ui-tooltip-icon .ui-icon{width:18px;height:14px;text-align:center;text-indent:0;font:normal bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em;}/*!Default tooltip style */ .ui-tooltip-default .ui-tooltip-titlebar,.ui-tooltip-default .ui-tooltip-content{border-color:#F1D031;background-color:#FFFFA3;color:#555;}.ui-tooltip-default .ui-tooltip-titlebar{background-color:#FFEF93;}.ui-tooltip-default .ui-tooltip-icon{border-color:#CCC;background:#F1F1F1;color:#777;}.ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{border-color:#AAA;color:#111;}.ui-tooltip .ui-tooltip-tip{margin:0 auto;overflow:hidden;z-index:10;}.ui-tooltip .ui-tooltip-tip,.ui-tooltip .ui-tooltip-tip *{position:absolute;line-height:.1px!important;font-size:.1px!important;color:#123456;background:transparent;border:0 dashed transparent;}.ui-tooltip .ui-tooltip-tip canvas{top:0;left:0;}#qtip-overlay{position:fixed;left:-10000em;top:-10000em;}#qtip-overlay.blurs{cursor:pointer;}#qtip-overlay div{position:absolute;left:0;top:0;width:100%;height:100%;background-color:black;opacity:.7;filter:alpha(opacity=70);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";}/*!Light tooltip style */ .ui-tooltip-light .ui-tooltip-titlebar,.ui-tooltip-light .ui-tooltip-content{border-color:#E2E2E2;color:#454545;}.ui-tooltip-light .ui-tooltip-content{background-color:white;}.ui-tooltip-light .ui-tooltip-titlebar{background-color:#f1f1f1;}/*!Dark tooltip style */ .ui-tooltip-dark .ui-tooltip-titlebar,.ui-tooltip-dark .ui-tooltip-content{border-color:#303030;color:#f3f3f3;}.ui-tooltip-dark .ui-tooltip-content{background-color:#505050;}.ui-tooltip-dark .ui-tooltip-titlebar{background-color:#404040;}.ui-tooltip-dark .ui-tooltip-icon{border-color:#444;}.ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}/*!Cream tooltip style */ .ui-tooltip-cream .ui-tooltip-titlebar,.ui-tooltip-cream .ui-tooltip-content{border-color:#F9E98E;color:#A27D35;}.ui-tooltip-cream .ui-tooltip-content{background-color:#FBF7AA;}.ui-tooltip-cream .ui-tooltip-titlebar{background-color:#F0DE7D;}.ui-tooltip-cream .ui-state-default .ui-tooltip-icon{background-position:-82px 0;}/*!Red tooltip style */ .ui-tooltip-red .ui-tooltip-titlebar,.ui-tooltip-red .ui-tooltip-content{border-color:#D95252;color:#912323;}.ui-tooltip-red .ui-tooltip-content{background-color:#F78B83;}.ui-tooltip-red .ui-tooltip-titlebar{background-color:#F06D65;}.ui-tooltip-red .ui-state-default .ui-tooltip-icon{background-position:-102px 0;}.ui-tooltip-red .ui-tooltip-icon{border-color:#D95252;}.ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{border-color:#D95252;}/*!Green tooltip style */ .ui-tooltip-green .ui-tooltip-titlebar,.ui-tooltip-green .ui-tooltip-content{border-color:#90D93F;color:#3F6219;}.ui-tooltip-green .ui-tooltip-content{background-color:#CAED9E;}.ui-tooltip-green .ui-tooltip-titlebar{background-color:#B0DE78;}.ui-tooltip-green .ui-state-default .ui-tooltip-icon{background-position:-42px 0;}/*!Blue tooltip style */ .ui-tooltip-blue .ui-tooltip-titlebar,.ui-tooltip-blue .ui-tooltip-content{border-color:#ADD9ED;color:#5E99BD;}.ui-tooltip-blue .ui-tooltip-content{background-color:#E5F6FE;}.ui-tooltip-blue .ui-tooltip-titlebar{background-color:#D0E9F5;}.ui-tooltip-blue .ui-state-default .ui-tooltip-icon{background-position:-2px 0;}/*!Add shadows to your tooltips in:FF3+,Chrome 2+,Opera 10.6+,IE6+,Safari 2+*/ .ui-tooltip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15);}.ui-tooltip-shadow .ui-tooltip-titlebar,.ui-tooltip-shadow .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.Shadow(Color='gray',Direction=135,Strength=3);-ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray',Direction=135,Strength=3)";_margin-bottom:-3px;.margin-bottom:-3px;}/*!Add rounded corners to your tooltips in:FF3+,Chrome 2+,Opera 10.6+,IE9+,Safari 2+*/ .ui-tooltip-rounded,.ui-tooltip-rounded .ui-tooltip-content,.ui-tooltip-tipsy,.ui-tooltip-tipsy .ui-tooltip-content,.ui-tooltip-youtube,.ui-tooltip-youtube .ui-tooltip-content{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;}.ui-tooltip-rounded .ui-tooltip-titlebar,.ui-tooltip-tipsy .ui-tooltip-titlebar,.ui-tooltip-youtube .ui-tooltip-titlebar{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}.ui-tooltip-rounded .ui-tooltip-titlebar+.ui-tooltip-content,.ui-tooltip-tipsy .ui-tooltip-titlebar+.ui-tooltip-content,.ui-tooltip-youtube .ui-tooltip-titlebar+.ui-tooltip-content{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;}/*!Youtube tooltip style */ .ui-tooltip-youtube{-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;}.ui-tooltip-youtube .ui-tooltip-titlebar,.ui-tooltip-youtube .ui-tooltip-content{_margin-bottom:0;.margin-bottom:0;background:transparent;background:rgba(0,0,0,0.85);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";color:white;border-color:#CCC;}.ui-tooltip-youtube .ui-tooltip-icon{border-color:#222;}.ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}.ui-tooltip-jtools{background:#232323;background:rgba(0,0,0,0.7);background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333;}.ui-tooltip-jtools .ui-tooltip-titlebar{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";}.ui-tooltip-jtools .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";}.ui-tooltip-jtools .ui-tooltip-titlebar,.ui-tooltip-jtools .ui-tooltip-content{background:transparent;color:white;border:0 dashed transparent;}.ui-tooltip-jtools .ui-tooltip-icon{border-color:#555;}.ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{border-color:#333;}.ui-tooltip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,0.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,0.4);box-shadow:4px 4px 5px rgba(0,0,0,0.4);}.ui-tooltip-cluetip .ui-tooltip-titlebar{background-color:#87876A;color:white;border:0 dashed transparent;}.ui-tooltip-cluetip .ui-tooltip-content{background-color:#D9D9C2;color:#111;border:0 dashed transparent;}.ui-tooltip-cluetip .ui-tooltip-icon{border-color:#808064;}.ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{border-color:#696952;color:#696952;}.ui-tooltip-tipsy{border:0;}.ui-tooltip-tipsy .ui-tooltip-titlebar,.ui-tooltip-tipsy .ui-tooltip-content{_margin-bottom:0;.margin-bottom:0;background:transparent;background:rgba(0,0,0,.87);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";color:white;border:0 transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:bold;line-height:16px;text-shadow:0 1px black;}.ui-tooltip-tipsy .ui-tooltip-titlebar{padding:6px 35px 0 10;}.ui-tooltip-tipsy .ui-tooltip-content{padding:6px 10;}.ui-tooltip-tipsy .ui-tooltip-icon{border-color:#222;text-shadow:none;}.ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{border-color:#303030;}.ui-tooltip-tipped .ui-tooltip-titlebar,.ui-tooltip-tipped .ui-tooltip-content{border:3px solid #959FA9;filter:none;-ms-filter:none;}.ui-tooltip-tipped .ui-tooltip-titlebar{background:#3A79B8;background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";color:white;font-weight:normal;font-family:serif;border-bottom-width:0;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}.ui-tooltip-tipped .ui-tooltip-content{background-color:#F9F9F9;color:#454545;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;}.ui-tooltip-tipped .ui-tooltip-icon{border:2px solid #285589;background:#285589;}.ui-tooltip-tipped .ui-tooltip-icon .ui-icon{background-color:#FBFBFB;color:#555;}.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{filter:none;-ms-filter:none;} \ No newline at end of file diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.min.js b/www/themes/profind/lib/qtip2/jquery.qtip.min.js new file mode 100644 index 0000000..6e9e15a --- /dev/null +++ b/www/themes/profind/lib/qtip2/jquery.qtip.min.js @@ -0,0 +1,13 @@ +/* +* qTip2 - Pretty powerful tooltips +* http://craigsworks.com/projects/qtip2/ +* +* Version: nightly +* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com +* +* Dual licensed under MIT or GPLv2 licenses +* http://en.wikipedia.org/wiki/MIT_License +* http://en.wikipedia.org/wiki/GNU_General_Public_License +* +* Date: Mon Apr 2 13:46:17.0000000000 2012 +*//*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true *//*global window: false, jQuery: false, console: false, define: false */(function(a){typeof define==="function"&&define.amd?define(["jquery"],a):a(jQuery)})(function(a){function D(b){var c=this,d=b.elements,e=d.tooltip,f=".bgiframe-"+b.id;a.extend(c,{init:function(){d.bgiframe=a(''),d.bgiframe.appendTo(e),e.bind("tooltipmove"+f,c.adjust)},adjust:function(){var a=b.get("dimensions"),c=b.plugins.tip,f=d.tip,g,h;h=parseInt(e.css("border-left-width"),10)||0,h={left:-h,top:-h},c&&f&&(g=c.corner.precedance==="x"?["width","left"]:["height","top"],h[g[1]]-=f[g[0]]()),d.bgiframe.css(h).css(a)},destroy:function(){d.bgiframe.remove(),e.unbind(f)}}),c.init()}function C(d){var e=this,f=d.options.show.modal,h=d.elements,i=h.tooltip,j="#qtip-overlay",k=".qtipmodal",l=k+d.id,n="is-modal-qtip",p=a(document.body),q;d.checks.modal={"^show.modal.(on|blur)$":function(){e.init(),h.overlay.toggle(i.is(":visible"))}},a.extend(e,{init:function(){if(!f.on)return e;q=e.create(),i.attr(n,b).css("z-index",g.modal.zindex+a(m+"["+n+"]").length).unbind(k).unbind(l).bind("tooltipshow"+k+" tooltiphide"+k,function(b,c,d){var f=b.originalEvent;if(b.target===i[0])if(f&&b.type==="tooltiphide"&&/mouse(leave|enter)/.test(f.type)&&a(f.relatedTarget).closest(q[0]).length)try{b.preventDefault()}catch(g){}else(!f||f&&!f.solo)&&e[b.type.replace("tooltip","")](b,d)}).bind("tooltipfocus"+k,function(b){if(!b.isDefaultPrevented()&&b.target===i[0]){var c=a(m).filter("["+n+"]"),d=g.modal.zindex+c.length,e=parseInt(i[0].style.zIndex,10);q[0].style.zIndex=d-1,c.each(function(){this.style.zIndex>e&&(this.style.zIndex-=1)}),c.end().filter("."+o).qtip("blur",b.originalEvent),i.addClass(o)[0].style.zIndex=d;try{b.preventDefault()}catch(f){}}}).bind("tooltiphide"+k,function(b){b.target===i[0]&&a("["+n+"]").filter(":visible").not(i).last().qtip("focus",b)}),f.escape&&a(window).unbind(l).bind("keydown"+l,function(a){a.keyCode===27&&i.hasClass(o)&&d.hide(a)}),f.blur&&h.overlay.unbind(l).bind("click"+l,function(a){i.hasClass(o)&&d.hide(a)});return e},create:function(){function d(){q.css({height:a(window).height(),width:a(window).width()})}var b=a(j);if(b.length)return h.overlay=b.insertAfter(a(m).last());q=h.overlay=a("
    ",{id:j.substr(1),html:"
    ",mousedown:function(){return c}}).insertAfter(a(m).last()),a(window).unbind(k).bind("resize"+k,d),d();return q},toggle:function(d,g,h){if(d&&d.isDefaultPrevented())return e;var j=f.effect,k=g?"show":"hide",o=q.is(":visible"),r=a("["+n+"]").filter(":visible").not(i),s;q||(q=e.create());if(q.is(":animated")&&o===g||!g&&r.length)return e;g?(q.css({left:0,top:0}),q.toggleClass("blurs",f.blur),p.bind("focusin"+l,function(b){var d=a(b.target),e=d.closest(".qtip"),f=e.length<1?c:parseInt(e[0].style.zIndex,10)>parseInt(i[0].style.zIndex,10);!f&&a(b.target).closest(m)[0]!==i[0]&&i.find("input:visible").filter(":first").focus()})):p.undelegate("*","focusin"+l),q.stop(b,c),a.isFunction(j)?j.call(q,g):j===c?q[k]():q.fadeTo(parseInt(h,10)||90,g?1:0,function(){g||a(this).hide()}),g||q.queue(function(a){q.css({left:"",top:""}),a()});return e},show:function(a,c){return e.toggle(a,b,c)},hide:function(a,b){return e.toggle(a,c,b)},destroy:function(){var b=q;b&&(b=a("["+n+"]").not(i).length<1,b?(h.overlay.remove(),a(window).unbind(k)):h.overlay.unbind(k+d.id),p.undelegate("*","focusin"+l));return i.removeAttr(n).unbind(k)}}),e.init()}function B(f,h){function w(a){var b=a.precedance==="y",c=n[b?"width":"height"],d=n[b?"height":"width"],e=a.string().indexOf("center")>-1,f=c*(e?.5:1),g=Math.pow,h=Math.round,i,j,k,l=Math.sqrt(g(f,2)+g(d,2)),m=[p/f*l,p/d*l];m[2]=Math.sqrt(g(m[0],2)-g(p,2)),m[3]=Math.sqrt(g(m[1],2)-g(p,2)),i=l+m[2]+m[3]+(e?0:m[0]),j=i/l,k=[h(j*d),h(j*c)];return{height:k[b?0:1],width:k[b?1:0]}}function v(b){var c=k.titlebar&&b.y==="top",d=c?k.titlebar:k.content,e=a.browser.mozilla,f=e?"-moz-":a.browser.webkit?"-webkit-":"",g=b.y+(e?"":"-")+b.x,h=f+(e?"border-radius-"+g:"border-"+g+"-radius");return parseInt(d.css(h),10)||parseInt(l.css(h),10)||0}function u(a,b,c){b=b?b:a[a.precedance];var d=l.hasClass(q),e=k.titlebar&&a.y==="top",f=e?k.titlebar:k.content,g="border-"+b+"-width",h;l.addClass(q),h=parseInt(f.css(g),10),h=(c?h||parseInt(l.css(g),10):h)||0,l.toggleClass(q,d);return h}function t(a,d,g,h){if(k.tip){var l=i.corner.clone(),n=g.adjusted,o=f.options.position.adjust.method.split(" "),p=o[0],q=o[1]||o[0],r={left:c,top:c,x:0,y:0},s,t={},u;i.corner.fixed!==b&&(p==="shift"&&l.precedance==="x"&&n.left&&l.y!=="center"?l.precedance=l.precedance==="x"?"y":"x":p==="flip"&&n.left&&(l.x=l.x==="center"?n.left>0?"left":"right":l.x==="left"?"right":"left"),q==="shift"&&l.precedance==="y"&&n.top&&l.x!=="center"?l.precedance=l.precedance==="y"?"x":"y":q==="flip"&&n.top&&(l.y=l.y==="center"?n.top>0?"top":"bottom":l.y==="top"?"bottom":"top"),l.string()!==m.corner.string()&&(m.top!==n.top||m.left!==n.left)&&i.update(l,c)),s=i.position(l,n),s.right!==e&&(s.left=-s.right),s.bottom!==e&&(s.top=-s.bottom),s.user=Math.max(0,j.offset);if(r.left=p==="shift"&&!!n.left)l.x==="center"?t["margin-left"]=r.x=s["margin-left"]-n.left:(u=s.right!==e?[n.left,-s.left]:[-n.left,s.left],(r.x=Math.max(u[0],u[1]))>u[0]&&(g.left-=n.left,r.left=c),t[s.right!==e?"right":"left"]=r.x);if(r.top=q==="shift"&&!!n.top)l.y==="center"?t["margin-top"]=r.y=s["margin-top"]-n.top:(u=s.bottom!==e?[n.top,-s.top]:[-n.top,s.top],(r.y=Math.max(u[0],u[1]))>u[0]&&(g.top-=n.top,r.top=c),t[s.bottom!==e?"bottom":"top"]=r.y);k.tip.css(t).toggle(!(r.x&&r.y||l.x==="center"&&r.y||l.y==="center"&&r.x)),g.left-=s.left.charAt?s.user:p!=="shift"||r.top||!r.left&&!r.top?s.left:0,g.top-=s.top.charAt?s.user:q!=="shift"||r.left||!r.left&&!r.top?s.top:0,m.left=n.left,m.top=n.top,m.corner=l.clone()}}var i=this,j=f.options.style.tip,k=f.elements,l=k.tooltip,m={top:0,left:0},n={width:j.width,height:j.height},o={},p=j.border||0,r=".qtip-tip",s=!!(a("")[0]||{}).getContext;i.mimic=i.corner=d,i.border=p,i.offset=j.offset,i.size=n,f.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){i.init()||i.destroy(),f.reposition()},"^style.tip.(height|width)$":function(){n={width:j.width,height:j.height},i.create(),i.update(),f.reposition()},"^content.title.text|style.(classes|widget)$":function(){k.tip&&i.update()}},a.extend(i,{init:function(){var b=i.detectCorner()&&(s||a.browser.msie);b&&(i.create(),i.update(),l.unbind(r).bind("tooltipmove"+r,t));return b},detectCorner:function(){var a=j.corner,d=f.options.position,e=d.at,h=d.my.string?d.my.string():d.my;if(a===c||h===c&&e===c)return c;a===b?i.corner=new g.Corner(h):a.string||(i.corner=new g.Corner(a),i.corner.fixed=b),m.corner=new g.Corner(i.corner.string());return i.corner.string()!=="centercenter"},detectColours:function(b){var c,d,e,g=k.tip.css("cssText",""),h=b||i.corner,m=h[h.precedance],p="border-"+m+"-color",r="border"+m.charAt(0)+m.substr(1)+"Color",s=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,t="background-color",u="transparent",v=" !important",w=a(document.body).css("color"),x=f.elements.content.css("color"),y=k.titlebar&&(h.y==="top"||h.y==="center"&&g.position().top+n.height/2+j.offset",{"class":"ui-tooltip-tip"}).css({width:b,height:c}).prependTo(l),s?a("").appendTo(k.tip)[0].getContext("2d").save():(d='',k.tip.html(d+d),a("*",k.tip).bind("click mousedown",function(a){a.stopPropagation()}))},update:function(e,f){var h=k.tip,l=h.children(),q=n.width,r=n.height,t="px solid ",v="px dashed transparent",x=j.mimic,y=Math.round,z,B,C,D,E;e||(e=m.corner||i.corner),x===c?x=e:(x=new g.Corner(x),x.precedance=e.precedance,x.x==="inherit"?x.x=e.x:x.y==="inherit"?x.y=e.y:x.x===x.y&&(x[e.precedance]=e[e.precedance])),z=x.precedance,i.detectColours(e),o.border!=="transparent"&&o.border!=="#123456"?(p=u(e,d,b),j.border===0&&p>0&&(o.fill=o.border),i.border=p=j.border!==b?j.border:p):i.border=p=0,C=A(x,q,r),i.size=E=w(e),h.css(E),e.precedance==="y"?D=[y(x.x==="left"?p:x.x==="right"?E.width-q-p:(E.width-q)/2),y(x.y==="top"?E.height-r:0)]:D=[y(x.x==="left"?E.width-q:0),y(x.y==="top"?p:x.y==="bottom"?E.height-r-p:(E.height-r)/2)],s?(l.attr(E),B=l[0].getContext("2d"),B.restore(),B.save(),B.clearRect(0,0,3e3,3e3),B.translate(D[0],D[1]),B.beginPath(),B.moveTo(C[0][0],C[0][1]),B.lineTo(C[1][0],C[1][1]),B.lineTo(C[2][0],C[2][1]),B.closePath(),B.fillStyle=o.fill,B.strokeStyle=o.border,B.lineWidth=p*2,B.lineJoin="miter",B.miterLimit=100,p&&B.stroke(),B.fill()):(C="m"+C[0][0]+","+C[0][1]+" l"+C[1][0]+","+C[1][1]+" "+C[2][0]+","+C[2][1]+" xe",D[2]=p&&/^(r|b)/i.test(e.string())?parseFloat(a.browser.version,10)===8?2:1:0,l.css({antialias:""+(x.string().indexOf("center")>-1),left:D[0]-D[2]*Number(z==="x"),top:D[1]-D[2]*Number(z==="y"),width:q+p,height:r+p}).each(function(b){var c=a(this);c[c.prop?"prop":"attr"]({coordsize:q+p+" "+(r+p),path:C,fillcolor:o.fill,filled:!!b,stroked:!b}).css({display:p||b?"block":"none"}),!b&&c.html()===""&&c.html('')})),f!==c&&i.position(e)},position:function(d){var e=k.tip,f={},g=Math.max(0,j.offset),h,l,m;if(j.corner===c||!e)return c;d=d||i.corner,h=d.precedance,l=w(d),m=[d.x,d.y],h==="x"&&m.reverse(),a.each(m,function(a,c){var e,i;c==="center"?(e=h==="y"?"left":"top",f[e]="50%",f["margin-"+e]=-Math.round(l[h==="y"?"width":"height"]/2)+g):(e=u(d,c,b),i=v(d),f[c]=a?p?u(d,c):0:g+(i>e?i:0))}),f[d[h]]-=l[h==="x"?"width":"height"],e.css({top:"",bottom:"",left:"",right:"",margin:""}).css(f);return f},destroy:function(){k.tip&&k.tip.remove(),l.unbind(r)}}),i.init()}function A(a,b,c){var d=Math.ceil(b/2),e=Math.ceil(c/2),f={bottomright:[[0,0],[b,c],[b,0]],bottomleft:[[0,0],[b,0],[0,c]],topright:[[0,c],[b,0],[b,c]],topleft:[[0,0],[0,c],[b,c]],topcenter:[[0,c],[d,0],[b,c]],bottomcenter:[[0,0],[b,0],[d,c]],rightcenter:[[0,0],[b,e],[0,c]],leftcenter:[[b,0],[b,c],[0,e]]};f.lefttop=f.bottomright,f.righttop=f.bottomleft,f.leftbottom=f.topright,f.rightbottom=f.topleft;return f[a.string()]}function z(d){var e=this,f=d.elements.tooltip,g=d.options.content.ajax,h=".qtip-ajax",i=/)<[^<]*)*<\/script>/gi,j=b,k=c,l;d.checks.ajax={"^content.ajax":function(a,b,c){b==="ajax"&&(g=c),b==="once"?e.init():g&&g.url?e.load():f.unbind(h)}},a.extend(e,{init:function(){g&&g.url&&f.unbind(h)[g.once?"one":"bind"]("tooltipshow"+h,e.load);return e},load:function(b,f){function r(a,b,c){!k&&a.status!==0&&d.set("content.text",b+": "+c)}function q(b){k||(m&&(b=a("
    ").append(b.replace(i,"")).find(m)),d.set("content.text",b))}function p(){k||(n&&(d.show(b.originalEvent),f=c),a.isFunction(g.complete)&&g.complete.apply(this,arguments))}var h=g.url.indexOf(" "),j=g.url,m,n=g.once&&!g.loading&&f;if(n)try{b.preventDefault()}catch(o){}else if(b&&b.isDefaultPrevented())return e;l&&l.abort&&l.abort(),h>-1&&(m=j.substr(h),j=j.substr(0,h)),l=a.ajax(a.extend({success:q,error:r,context:d},g,{url:j,complete:p}))},destroy:function(){l&&l.abort&&l.abort(),k=b}}),e.init()}function y(e,h){var i,j,k,l,m,n=a(this),o=a(document.body),p=this===document?o:n,q=n.metadata?n.metadata(h.metadata):d,r=h.metadata.type==="html5"&&q?q[h.metadata.name]:d,s=n.data(h.metadata.name||"qtipopts");try{s=typeof s==="string"?(new Function("return "+s))():s}catch(u){v("Unable to parse HTML5 attribute data: "+s)}l=a.extend(b,{},f.defaults,h,typeof s==="object"?w(s):d,w(r||q)),j=l.position,l.id=e;if("boolean"===typeof l.content.text){k=n.attr(l.content.attr);if(l.content.attr!==c&&k)l.content.text=k;else{v("Unable to locate content for tooltip! Aborting render of tooltip on element: ",n);return c}}j.container.length||(j.container=o),j.target===c&&(j.target=p),l.show.target===c&&(l.show.target=p),l.show.solo===b&&(l.show.solo=j.container.closest("body")),l.hide.target===c&&(l.hide.target=p),l.position.viewport===b&&(l.position.viewport=j.container),j.container=j.container.eq(0),j.at=new g.Corner(j.at),j.my=new g.Corner(j.my);if(a.data(this,"qtip"))if(l.overwrite)n.qtip("destroy");else if(l.overwrite===c)return c;l.suppress&&(m=a.attr(this,"title"))&&a(this).removeAttr("title").attr(t,m),i=new x(n,l,e,!!k),a.data(this,"qtip",i),n.bind("remove.qtip-"+e+" removeqtip.qtip-"+e,function(){i.destroy()});return i}function x(r,s,v,x){function Q(){var b=[s.show.target[0],s.hide.target[0],y.rendered&&F.tooltip[0],s.position.container[0],s.position.viewport[0],window,document];y.rendered?a([]).pushStack(a.grep(b,function(a){return typeof a==="object"})).unbind(E):s.show.target.unbind(E+"-create")}function P(){function o(a){D.is(":visible")&&y.reposition(a)}function n(a){if(D.hasClass(l))return c;clearTimeout(y.timers.inactive),y.timers.inactive=setTimeout(function(){y.hide(a)},s.hide.inactive)}function k(b){if(D.hasClass(l)||B||C)return c;var f=a(b.relatedTarget||b.target),g=f.closest(m)[0]===D[0],h=f[0]===e.show[0];clearTimeout(y.timers.show),clearTimeout(y.timers.hide);if(d.target==="mouse"&&g||s.hide.fixed&&(/mouse(out|leave|move)/.test(b.type)&&(g||h)))try{b.preventDefault(),b.stopImmediatePropagation()}catch(i){}else s.hide.delay>0?y.timers.hide=setTimeout(function(){y.hide(b)},s.hide.delay):y.hide(b)}function j(a){if(D.hasClass(l))return c;clearTimeout(y.timers.show),clearTimeout(y.timers.hide);var d=function(){y.toggle(b,a)};s.show.delay>0?y.timers.show=setTimeout(d,s.show.delay):d()}var d=s.position,e={show:s.show.target,hide:s.hide.target,viewport:a(d.viewport),document:a(document),body:a(document.body),window:a(window)},g={show:a.trim(""+s.show.event).split(" "),hide:a.trim(""+s.hide.event).split(" ")},i=a.browser.msie&&parseInt(a.browser.version,10)===6;D.bind("mouseenter"+E+" mouseleave"+E,function(a){var b=a.type==="mouseenter";b&&y.focus(a),D.toggleClass(p,b)}),s.hide.fixed&&(e.hide=e.hide.add(D),D.bind("mouseover"+E,function(){D.hasClass(l)||clearTimeout(y.timers.hide)})),/mouse(out|leave)/i.test(s.hide.event)?s.hide.leave==="window"&&e.window.bind("mouseout"+E+" blur"+E,function(a){/select|option/.test(a.target)&&!a.relatedTarget&&y.hide(a)}):/mouse(over|enter)/i.test(s.show.event)&&e.hide.bind("mouseleave"+E,function(a){clearTimeout(y.timers.show)}),(""+s.hide.event).indexOf("unfocus")>-1&&d.container.closest("html").bind("mousedown"+E,function(b){var c=a(b.target),d=!D.hasClass(l)&&D.is(":visible"),e=c.parents(m).filter(D[0]).length>0;c[0]!==r[0]&&c[0]!==D[0]&&!e&&!r.has(c[0]).length&&!c.attr("disabled")&&y.hide(b)}),"number"===typeof s.hide.inactive&&(e.show.bind("qtip-"+v+"-inactive",n),a.each(f.inactiveEvents,function(a,b){e.hide.add(F.tooltip).bind(b+E+"-inactive",n)})),a.each(g.hide,function(b,c){var d=a.inArray(c,g.show),f=a(e.hide);d>-1&&f.add(e.show).length===f.length||c==="unfocus"?(e.show.bind(c+E,function(a){D.is(":visible")?k(a):j(a)}),delete g.show[d]):e.hide.bind(c+E,k)}),a.each(g.show,function(a,b){e.show.bind(b+E,j)}),"number"===typeof s.hide.distance&&e.show.add(D).bind("mousemove"+E,function(a){var b=G.origin||{},c=s.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&y.hide(a)}),d.target==="mouse"&&(e.show.bind("mousemove"+E,function(a){h={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),d.adjust.mouse&&(s.hide.event&&(D.bind("mouseleave"+E,function(a){(a.relatedTarget||a.target)!==e.show[0]&&y.hide(a)}),F.target.bind("mouseenter"+E+" mouseleave"+E,function(a){G.onTarget=a.type==="mouseenter"})),e.document.bind("mousemove"+E,function(a){G.onTarget&&!D.hasClass(l)&&D.is(":visible")&&y.reposition(a||h)}))),(d.adjust.resize||e.viewport.length)&&(a.event.special.resize?e.viewport:e.window).bind("resize"+E,o),(e.viewport.length||i&&D.css("position")==="fixed")&&e.viewport.bind("scroll"+E,o)}function O(b,d){function g(b){function i(e){e&&(delete h[e.src],clearTimeout(y.timers.img[e.src]),a(e).unbind(E)),a.isEmptyObject(h)&&(y.redraw(),d!==c&&y.reposition(G.event),b())}var g,h={};if((g=f.find("img[src]:not([height]):not([width])")).length===0)return i();g.each(function(b,c){if(h[c.src]===e){var d=0,f=3;(function g(){if(c.height||c.width||d>f)return i(c);d+=1,y.timers.img[c.src]=setTimeout(g,700)})(),a(c).bind("error"+E+" load"+E,function(){i(this)}),h[c.src]=c}})}var f=F.content;if(!y.rendered||!b)return c;a.isFunction(b)&&(b=b.call(r,G.event,y)||""),b.jquery&&b.length>0?f.empty().append(b.css({display:"block"})):f.html(b),y.rendered<0?D.queue("fx",g):(C=0,g(a.noop));return y}function N(b,d){var e=F.title;if(!y.rendered||!b)return c;a.isFunction(b)&&(b=b.call(r,G.event,y));if(b===c||!b&&b!=="")return J(c);b.jquery&&b.length>0?e.empty().append(b.css({display:"block"})):e.html(b),y.redraw(),d!==c&&y.rendered&&D.is(":visible")&&y.reposition(G.event)}function M(a){var b=F.button,d=F.title;if(!y.rendered)return c;a?(d||L(),K()):b.remove()}function L(){var c=A+"-title";F.titlebar&&J(),F.titlebar=a("
    ",{"class":j+"-titlebar "+(s.style.widget?"ui-widget-header":"")}).append(F.title=a("
    ",{id:c,"class":j+"-title","aria-atomic":b})).insertBefore(F.content).delegate(".ui-tooltip-close","mousedown keydown mouseup keyup mouseout",function(b){a(this).toggleClass("ui-state-active ui-state-focus",b.type.substr(-4)==="down")}).delegate(".ui-tooltip-close","mouseover mouseout",function(b){a(this).toggleClass("ui-state-hover",b.type==="mouseover")}),s.content.title.button?K():y.rendered&&y.redraw()}function K(){var b=s.content.title.button,d=typeof b==="string",e=d?b:"Close tooltip";F.button&&F.button.remove(),b.jquery?F.button=b:F.button=a("",{"class":"ui-state-default ui-tooltip-close "+(s.style.widget?"":j+"-icon"),title:e,"aria-label":e}).prepend(a("",{"class":"ui-icon ui-icon-close",html:"×"})),F.button.appendTo(F.titlebar).attr("role","button").click(function(a){D.hasClass(l)||y.hide(a);return c}),y.redraw()}function J(a){F.title&&(F.titlebar.remove(),F.titlebar=F.title=F.button=d,a!==c&&y.reposition())}function I(){var a=s.style.widget;D.toggleClass(k,a).toggleClass(n,s.style.def&&!a),F.content.toggleClass(k+"-content",a),F.titlebar&&F.titlebar.toggleClass(k+"-header",a),F.button&&F.button.toggleClass(j+"-icon",!a)}function H(a){var b=0,c,d=s,e=a.split(".");while(d=d[e[b++]])b0&&!a("#"+i).length&&(D[0].id=i,F.content[0].id=i+"-content",F.title[0].id=i+"-title")},"^content.text$":function(a,b,c){O(c)},"^content.title.text$":function(a,b,c){if(!c)return J();!F.title&&c&&L(),N(c)},"^content.title.button$":function(a,b,c){M(c)},"^position.(my|at)$":function(a,b,c){"string"===typeof c&&(a[b]=new g.Corner(c))},"^position.container$":function(a,b,c){y.rendered&&D.appendTo(c)},"^show.ready$":function(){y.rendered?y.toggle(b):y.render(1)},"^style.classes$":function(a,b,c){D.attr("class",j+" qtip ui-helper-reset "+c)},"^style.widget|content.title":I,"^events.(render|show|move|hide|focus|blur)$":function(b,c,d){D[(a.isFunction(d)?"":"un")+"bind"]("tooltip"+c,d)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){var a=s.position;D.attr("tracking",a.target==="mouse"&&a.adjust.mouse),Q(),P()}},a.extend(y,{render:function(d){if(y.rendered)return y;var e=s.content.text,f=s.content.title.text,h=s.position,i=a.Event("tooltiprender");a.attr(r[0],"aria-describedby",A),D=F.tooltip=a("
    ",{id:A,"class":j+" qtip ui-helper-reset "+n+" "+s.style.classes+" "+j+"-pos-"+s.position.my.abbrev(),width:s.style.width||"",height:s.style.height||"",tracking:h.target==="mouse"&&h.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":c,"aria-describedby":A+"-content","aria-hidden":b}).toggleClass(l,G.disabled).data("qtip",y).appendTo(s.position.container).append(F.content=a("
    ",{"class":j+"-content",id:A+"-content","aria-atomic":b})),y.rendered=-1,B=C=1,f&&(L(),a.isFunction(f)||N(f,c)),a.isFunction(e)||O(e,c),y.rendered=b,I(),a.each(s.events,function(b,c){a.isFunction(c)&&D.bind(b==="toggle"?"tooltipshow tooltiphide":"tooltip"+b,c)}),a.each(g,function(){this.initialize==="render"&&this(y)}),P(),D.queue("fx",function(a){i.originalEvent=G.event,D.trigger(i,[y]),B=C=0,y.redraw(),(s.show.ready||d)&&y.toggle(b,G.event,c),a()});return y},get:function(a){var b,c;switch(a.toLowerCase()){case"dimensions":b={height:D.outerHeight(),width:D.outerWidth()};break;case"offset":b=g.offset(D,s.position.container);break;default:c=H(a.toLowerCase()),b=c[0][c[1]],b=b.precedance?b.string():b}return b},set:function(e,f){function m(a,b){var c,d,e;for(c in k)for(d in k[c])if(e=(new RegExp(d,"i")).exec(a))b.push(e),k[c][d].apply(y,b)}var g=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,h=/^content\.(title|attr)|style/i,i=c,j=c,k=y.checks,l;"string"===typeof e?(l=e,e={},e[l]=f):e=a.extend(b,{},e),a.each(e,function(b,c){var d=H(b.toLowerCase()),f;f=d[0][d[1]],d[0][d[1]]="object"===typeof c&&c.nodeType?a(c):c,e[b]=[d[0],d[1],c,f],i=g.test(b)||i,j=h.test(b)||j}),w(s),B=C=1,a.each(e,m),B=C=0,D.is(":visible")&&y.rendered&&(i&&y.reposition(s.position.target==="mouse"?d:G.event),j&&y.redraw());return y},toggle:function(e,f){function r(){e?(a.browser.msie&&D[0].style.removeAttribute("filter"),D.css("overflow",""),"string"===typeof i.autofocus&&a(i.autofocus,D).focus(),i.target.trigger("qtip-"+v+"-inactive")):D.css({display:"",visibility:"",opacity:"",left:"",top:""}),q=a.Event("tooltip"+(e?"visible":"hidden")),q.originalEvent=f?G.event:d,D.trigger(q,[y])}if(!y.rendered)return e?y.render(1):y;var g=e?"show":"hide",i=s[g],j=D.is(":visible"),k=!f||i.target.length<2||G.target[0]===f.target,l=f&&i.target.add(f.target).length!==i.target.length,n=s.position,o=s.content,p,q;(typeof e).search("boolean|number")&&(e=!j);if(!D.is(":animated")&&j===e&&k)return y;if(f){if(/over|enter/.test(f.type)&&/out|leave/.test(G.event.type)&&s.show.target.add(f.target).length===s.show.target.length&&D.has(f.relatedTarget).length)return y;G.event=a.extend({},f)}q=a.Event("tooltip"+g),q.originalEvent=f?G.event:d,D.trigger(q,[y,90]);if(q.isDefaultPrevented())return y;a.attr(D[0],"aria-hidden",!e),e?(G.origin=a.extend({},h),y.focus(f),a.isFunction(o.text)&&O(o.text,c),a.isFunction(o.title.text)&&N(o.title.text,c),!u&&n.target==="mouse"&&n.adjust.mouse&&(a(document).bind("mousemove.qtip",function(a){h={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),u=b),y.reposition(f,arguments[2]),(q.solo=!!i.solo)&&a(m,i.solo).not(D).qtip("hide",q)):(clearTimeout(y.timers.show),delete G.origin,u&&!a(m+'[tracking="true"]:visible',i.solo).not(D).length&&(a(document).unbind("mousemove.qtip"),u=c),y.blur(f)),D.stop(l,!l),i.effect===c?(D[g](),r.call(D)):a.isFunction(i.effect)?(i.effect.call(D,y),D.queue("fx",function(a){r(),a()})):D.fadeTo(90,e?1:0,r),e&&i.target.trigger("qtip-"+v+"-inactive");return y},show:function(a){return y.toggle(b,a)},hide:function(a){return y.toggle(c,a)},focus:function(b){if(!y.rendered)return y;var c=a(m),d=parseInt(D[0].style.zIndex,10),e=f.zindex+c.length,g=a.extend({},b),h,i;D.hasClass(o)||(i=a.Event("tooltipfocus"),i.originalEvent=g,D.trigger(i,[y,e]),i.isDefaultPrevented()||(d!==e&&(c.each(function(){this.style.zIndex>d&&(this.style.zIndex=this.style.zIndex-1)}),c.filter("."+o).qtip("blur",g)),D.addClass(o)[0].style.zIndex=e));return y},blur:function(b){var c=a.extend({},b),d;D.removeClass(o),d=a.Event("tooltipblur"),d.originalEvent=c,D.trigger(d,[y]);return y},reposition:function(b,d){if(!y.rendered||B)return y;B=1;var e=s.position.target,f=s.position,i=f.my,k=f.at,l=f.adjust,m=l.method.split(" "),n=D.outerWidth(),o=D.outerHeight(),p=0,q=0,r=a.Event("tooltipmove"),t=D.css("position")==="fixed",u=f.viewport,v={left:0,top:0},w=f.container,x=c,A=y.plugins.tip,C={horizontal:m[0],vertical:m[1]=m[1]||m[0],enabled:u.jquery&&e[0]!==window&&e[0]!==z&&l.method!=="none",left:function(a){var b=C.horizontal==="shift",c=-w.offset.left+u.offset.left+u.scrollLeft,d=i.x==="left"?n:i.x==="right"?-n:-n/2,e=k.x==="left"?p:k.x==="right"?-p:-p/2,f=A&&A.size?A.size.width||0:0,g=A&&A.corner&&A.corner.precedance==="x"&&!b?f:0,h=c-a+g,j=a+n-u.width-c+g,m=d-(i.precedance==="x"||i.x===i.y?e:0)-(k.x==="center"?p/2:0),o=i.x==="center";b?(g=A&&A.corner&&A.corner.precedance==="y"?f:0,m=(i.x==="left"?1:-1)*d-g,v.left+=h>0?h:j>0?-j:0,v.left=Math.max(-w.offset.left+u.offset.left+(g&&A.corner.x==="center"?A.offset:0),a-m,Math.min(Math.max(-w.offset.left+u.offset.left+u.width,a+m),v.left))):(h>0&&(i.x!=="left"||j>0)?v.left-=m:j>0&&(i.x!=="right"||h>0)&&(v.left-=o?-m:m),v.left!==a&&o&&(v.left-=l.x),v.leftj&&(v.left=a));return v.left-a},top:function(a){var b=C.vertical==="shift",c=-w.offset.top+u.offset.top+u.scrollTop,d=i.y==="top"?o:i.y==="bottom"?-o:-o/2,e=k.y==="top"?q:k.y==="bottom"?-q:-q/2,f=A&&A.size?A.size.height||0:0,g=A&&A.corner&&A.corner.precedance==="y"&&!b?f:0,h=c-a+g,j=a+o-u.height-c+g,m=d-(i.precedance==="y"||i.x===i.y?e:0)-(k.y==="center"?q/2:0),n=i.y==="center";b?(g=A&&A.corner&&A.corner.precedance==="x"?f:0,m=(i.y==="top"?1:-1)*d-g,v.top+=h>0?h:j>0?-j:0,v.top=Math.max(-w.offset.top+u.offset.top+(g&&A.corner.x==="center"?A.offset:0),a-m,Math.min(Math.max(-w.offset.top+u.offset.top+u.height,a+m),v.top))):(h>0&&(i.y!=="top"||j>0)?v.top-=m:j>0&&(i.y!=="bottom"||h>0)&&(v.top-=n?-m:m),v.top!==a&&n&&(v.top-=l.y),v.top<0&&-v.top>j&&(v.top=a));return v.top-a}},E;if(a.isArray(e)&&e.length===2)k={x:"left",y:"top"},v={left:e[0],top:e[1]};else if(e==="mouse"&&(b&&b.pageX||G.event.pageX))k={x:"left",y:"top"},b=(b&&(b.type==="resize"||b.type==="scroll")?G.event:b&&b.pageX&&b.type==="mousemove"?b:h&&h.pageX&&(l.mouse||!b||!b.pageX)?{pageX:h.pageX,pageY:h.pageY}:!l.mouse&&G.origin&&G.origin.pageX&&s.show.distance?G.origin:b)||b||G.event||h||{},v={top:b.pageY,left:b.pageX};else{e==="event"?b&&b.target&&b.type!=="scroll"&&b.type!=="resize"?e=G.target=a(b.target):e=G.target:e=G.target=a(e.jquery?e:F.target),e=a(e).eq(0);if(e.length===0)return y;e[0]===document||e[0]===window?(p=g.iOS?window.innerWidth:e.width(),q=g.iOS?window.innerHeight:e.height(),e[0]===window&&(v={top:(u||e).scrollTop(),left:(u||e).scrollLeft()})):e.is("area")&&g.imagemap?v=g.imagemap(e,k,C.enabled?m:c):e[0].namespaceURI==="http://www.w3.org/2000/svg"&&g.svg?v=g.svg(e,k):(p=e.outerWidth(),q=e.outerHeight(),v=g.offset(e,w)),v.offset&&(p=v.width,q=v.height,x=v.flipoffset,v=v.offset);if(g.iOS<4.1&&g.iOS>3.1||g.iOS==4.3||!g.iOS&&t)E=a(window),v.left-=E.scrollLeft(),v.top-=E.scrollTop();v.left+=k.x==="right"?p:k.x==="center"?p/2:0,v.top+=k.y==="bottom"?q:k.y==="center"?q/2:0}v.left+=l.x+(i.x==="right"?-n:i.x==="center"?-n/2:0),v.top+=l.y+(i.y==="bottom"?-o:i.y==="center"?-o/2:0),C.enabled?(u={elem:u,height:u[(u[0]===window?"h":"outerH")+"eight"](),width:u[(u[0]===window?"w":"outerW")+"idth"](),scrollLeft:t?0:u.scrollLeft(),scrollTop:t?0:u.scrollTop(),offset:u.offset()||{left:0,top:0}},w={elem:w,scrollLeft:w.scrollLeft(),scrollTop:w.scrollTop(),offset:w.offset()||{left:0,top:0}},v.adjusted={left:C.horizontal!=="none"?C.left(v.left):0,top:C.vertical!=="none"?C.top(v.top):0},v.adjusted.left+v.adjusted.top&&D.attr("class",D[0].className.replace(/ui-tooltip-pos-\w+/i,j+"-pos-"+i.abbrev())),x&&v.adjusted.left&&(v.left+=x.left),x&&v.adjusted.top&&(v.top+=x.top)):v.adjusted={left:0,top:0},r.originalEvent=a.extend({},b),D.trigger(r,[y,v,u.elem||u]);if(r.isDefaultPrevented())return y;delete v.adjusted,d===c||isNaN(v.left)||isNaN(v.top)||e==="mouse"||!a.isFunction(f.effect)?D.css(v):a.isFunction(f.effect)&&(f.effect.call(D,y,a.extend({},v)),D.queue(function(b){a(this).css({opacity:"",height:""}),a.browser.msie&&this.style.removeAttribute("filter"),b()})),B=0;return y},redraw:function(){if(y.rendered<1||C)return y;var a=s.position.container,b,c,d,e;C=1,s.style.height&&D.css("height",s.style.height),s.style.width?D.css("width",s.style.width):(D.css("width","").addClass(q),c=D.width()+1,d=D.css("max-width")||"",e=D.css("min-width")||"",b=(d+e).indexOf("%")>-1?a.width()/100:0,d=(d.indexOf("%")>-1?b:1)*parseInt(d,10)||c,e=(e.indexOf("%")>-1?b:1)*parseInt(e,10)||0,c=d+e?Math.min(Math.max(c,e),d):c,D.css("width",Math.round(c)).removeClass(q)),C=0;return y},disable:function(b){"boolean"!==typeof b&&(b=!D.hasClass(l)&&!G.disabled),y.rendered?(D.toggleClass(l,b),a.attr(D[0],"aria-disabled",b)):G.disabled=!!b;return y},enable:function(){return y.disable(c)},destroy:function(){var b=r[0],c=a.attr(b,t),d=r.data("qtip");y.rendered&&(D.stop(1,0).remove(),a.each(y.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(y.timers.show),clearTimeout(y.timers.hide),Q();if(!d||y===d)a.removeData(b,"qtip"),s.suppress&&c&&(a.attr(b,"title",c),r.removeAttr(t)),r.removeAttr("aria-describedby");r.unbind(".qtip-"+v),delete i[y.id];return r}})}function w(b){var e;if(!b||"object"!==typeof b)return c;if(b.metadata===d||"object"!==typeof b.metadata)b.metadata={type:b.metadata};if("content"in b){if(b.content===d||"object"!==typeof b.content||b.content.jquery)b.content={text:b.content};e=b.content.text||c,!a.isFunction(e)&&(!e&&!e.attr||e.length<1||"object"===typeof e&&!e.jquery)&&(b.content.text=c);if("title"in b.content){if(b.content.title===d||"object"!==typeof b.content.title)b.content.title={text:b.content.title};e=b.content.title.text||c,!a.isFunction(e)&&(!e&&!e.attr||e.length<1||"object"===typeof e&&!e.jquery)&&(b.content.title.text=c)}}if("position"in b)if(b.position===d||"object"!==typeof b.position)b.position={my:b.position,at:b.position};if("show"in b)if(b.show===d||"object"!==typeof b.show)b.show.jquery?b.show={target:b.show}:b.show={event:b.show};if("hide"in b)if(b.hide===d||"object"!==typeof b.hide)b.hide.jquery?b.hide={target:b.hide}:b.hide={event:b.hide};if("style"in b)if(b.style===d||"object"!==typeof b.style)b.style={classes:b.style};a.each(g,function(){this.sanitize&&this.sanitize(b)});return b}function v(){v.history=v.history||[],v.history.push(arguments);if("object"===typeof console){var a=console[console.warn?"warn":"log"],b=Array.prototype.slice.call(arguments),c;typeof arguments[0]==="string"&&(b[0]="qTip2: "+b[0]),c=a.apply?a.apply(console,b):a(b)}}"use strict";var b=!0,c=!1,d=null,e,f,g,h,i={},j="ui-tooltip",k="ui-widget",l="ui-state-disabled",m="div.qtip."+j,n=j+"-default",o=j+"-focus",p=j+"-hover",q=j+"-fluid",r="-31000px",s="_replacedByqTip",t="oldtitle",u;f=a.fn.qtip=function(g,h,i){var j=(""+g).toLowerCase(),k=d,l=a.makeArray(arguments).slice(1),m=l[l.length-1],n=this[0]?a.data(this[0],"qtip"):d;if(!arguments.length&&n||j==="api")return n;if("string"===typeof g){this.each(function(){var d=a.data(this,"qtip");if(!d)return b;m&&m.timeStamp&&(d.cache.event=m);if(j!=="option"&&j!=="options"||!h)d[j]&&d[j].apply(d[j],l);else if(a.isPlainObject(h)||i!==e)d.set(h,i);else{k=d.get(h);return c}});return k!==d?k:this}if("object"===typeof g||!arguments.length){n=w(a.extend(b,{},g));return f.bind.call(this,n,m)}},f.bind=function(d,j){return this.each(function(k){function r(b){function d(){p.render(typeof b==="object"||l.show.ready),m.show.add(m.hide).unbind(o)}if(p.cache.disabled)return c;p.cache.event=a.extend({},b),p.cache.target=b?a(b.target):[e],l.show.delay>0?(clearTimeout(p.timers.show),p.timers.show=setTimeout(d,l.show.delay),n.show!==n.hide&&m.hide.bind(n.hide,function(){clearTimeout(p.timers.show)})):d()}var l,m,n,o,p,q;q=a.isArray(d.id)?d.id[k]:d.id,q=!q||q===c||q.length<1||i[q]?f.nextid++:i[q]=q,o=".qtip-"+q+"-create",p=y.call(this,q,d);if(p===c)return b;l=p.options,a.each(g,function(){this.initialize==="initialize"&&this(p)}),m={show:l.show.target,hide:l.hide.target},n={show:a.trim(""+l.show.event).replace(/ /g,o+" ")+o,hide:a.trim(""+l.hide.event).replace(/ /g,o+" ")+o},/mouse(over|enter)/i.test(n.show)&&!/mouse(out|leave)/i.test(n.hide)&&(n.hide+=" mouseleave"+o),m.show.bind("mousemove"+o,function(a){h={pageX:a.pageX,pageY:a.pageY,type:"mousemove"},p.cache.onTarget=b}),m.show.bind(n.show,r),(l.show.ready||l.prerender)&&r(j)})},g=f.plugins={Corner:function(a){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,"center").toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase();var b=a.charAt(0);this.precedance=b==="t"||b==="b"?"y":"x",this.string=function(){return this.precedance==="y"?this.y+this.x:this.x+this.y},this.abbrev=function(){var a=this.x.substr(0,1),b=this.y.substr(0,1);return a===b?a:a==="c"||a!=="c"&&b!=="c"?b+a:a+b},this.clone=function(){return{x:this.x,y:this.y,precedance:this.precedance,string:this.string,abbrev:this.abbrev,clone:this.clone}}},offset:function(b,c){function j(a,b){d.left+=b*a.scrollLeft(),d.top+=b*a.scrollTop()}var d=b.offset(),e=b.closest("body")[0],f=c,g,h,i;if(f){do f.css("position")!=="static"&&(h=f.position(),d.left-=h.left+(parseInt(f.css("borderLeftWidth"),10)||0)+(parseInt(f.css("marginLeft"),10)||0),d.top-=h.top+(parseInt(f.css("borderTopWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0),!g&&(i=f.css("overflow"))!=="hidden"&&i!=="visible"&&(g=f));while((f=a(f[0].offsetParent)).length);g&&g[0]!==e&&j(g,1)}return d},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_","."))||c,fn:{attr:function(b,c){if(this.length){var d=this[0],e="title",f=a.data(d,"qtip");if(b===e&&f&&"object"===typeof f&&f.options.suppress){if(arguments.length<2)return a.attr(d,t);f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",c);return this.attr(t,c)}}return a.fn["attr"+s].apply(this,arguments)},clone:function(b){var c=a([]),d="title",e=a.fn["clone"+s].apply(this,arguments);b||e.filter("["+t+"]").attr("title",function(){return a.attr(this,t)}).removeAttr(t);return e}}},a.each(g.fn,function(c,d){if(!d||a.fn[c+s])return b;var e=a.fn[c+s]=a.fn[c];a.fn[c]=function(){return d.apply(this,arguments)||e.apply(this,arguments)}}),a.ui||(a["cleanData"+s]=a.cleanData,a.cleanData=function(b){for(var c=0,d;(d=b[c])!==e;c++)try{a(d).triggerHandler("removeqtip")}catch(f){}a["cleanData"+s](b)}),f.version="nightly",f.nextid=0,f.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),f.zindex=15e3,f.defaults={prerender:c,id:c,overwrite:b,suppress:b,content:{text:b,attr:"title",title:{text:c,button:c}},position:{my:"top left",at:"bottom right",target:c,container:c,viewport:c,adjust:{x:0,y:0,mouse:b,resize:b,method:"flip flip"},effect:function(b,d,e){a(this).animate(d,{duration:200,queue:c})}},show:{target:c,event:"mouseenter",effect:b,delay:90,solo:c,ready:c,autofocus:c},hide:{target:c,event:"mouseleave",effect:b,delay:0,fixed:c,inactive:c,leave:"window",distance:c},style:{classes:"",widget:c,width:c,height:c,def:b},events:{render:d,move:d,show:d,hide:d,toggle:d,visible:d,hidden:d,focus:d,blur:d}},g.ajax=function(a){var b=a.plugins.ajax;return"object"===typeof b?b:a.plugins.ajax=new z(a)},g.ajax.initialize="render",g.ajax.sanitize=function(a){var b=a.content,c;b&&"ajax"in b&&(c=b.ajax,typeof c!=="object"&&(c=a.content.ajax={url:c}),"boolean"!==typeof c.once&&c.once&&(c.once=!!c.once))},a.extend(b,f.defaults,{content:{ajax:{loading:b,once:b}}}),g.imagemap=function(b,c,d){function n(a,b,c){var d=0,e=1,f=1,g=0,h=0,i=a.width,j=a.height;while(i>0&&j>0&&e>0&&f>0){i=Math.floor(i/2),j=Math.floor(j/2),c.x==="left"?e=i:c.x==="right"?e=a.width-i:e+=Math.floor(i/2),c.y==="top"?f=j:c.y==="bottom"?f=a.height-j:f+=Math.floor(j/2),d=b.length;while(d--){if(b.length<2)break;g=b[d][0]-a.offset.left,h=b[d][1]-a.offset.top,(c.x==="left"&&g>=e||c.x==="right"&&g<=e||c.x==="center"&&(ga.width-e)||c.y==="top"&&h>=f||c.y==="bottom"&&h<=f||c.y==="center"&&(ha.height-f))&&b.splice(d,1)}}return{left:b[0][0],top:b[0][1]}}b.jquery||(b=a(b));var e=(b[0].shape||b.attr("shape")).toLowerCase(),f=(b[0].coords||b.attr("coords")).split(","),g=[],h=a('img[usemap="#'+b.parent("map").attr("name")+'"]'),i=h.offset(),j={width:0,height:0,offset:{top:1e10,right:0,bottom:0,left:1e10}},k=0,l=0,m;i.left+=Math.ceil((h.outerWidth()-h.width())/2),i.top+=Math.ceil((h.outerHeight()-h.height())/2);if(e==="poly"){k=f.length;while(k--)l=[parseInt(f[--k],10),parseInt(f[k+1],10)],l[0]>j.offset.right&&(j.offset.right=l[0]),l[0]j.offset.bottom&&(j.offset.bottom=l[1]),l[1] 20fps, 3 <=> 15fps, ... + +(Synchronous) Trigger +--------------------- + +Triggering those events is achieved using jQuery's standard API: + + $(window).trigger( "debouncedresize" ); + +It's also possible to execute the handler of any listener synchronously (without the delays): + + $(window).trigger( "throttledresize", [true] ); + +Minimalist Standalone Version +============================= + +Most of the time, I find myself using `debouncedresize` just to register a single listener on `window`. +As it turns out, all the features I need actually fit in 91 bytes: + + // debulked onresize handler + function on_resize(c,t){onresize=function(){clearTimeout(t);t=setTimeout(c,100)};return c}; + +Using it is pretty simple: + + on_resize(function() { + // handle the resize event here + ... + }); + +Initializing a page (by executing the resize handler when the page loads) couldn't be easier: + + on_resize(function() { + ... + })(); // these parenthesis does the trick + +No files are provided for this function, simply copy/paste it from this README. + +License +======= + +MIT licensed http://louisremi.mit-license.org/ + +Copyright (c) 2012 [Louis-Rémi Babé](http://twitter.com/louis_remi). \ No newline at end of file diff --git a/www/themes/profind/lib/smartresize/jquery.debouncedresize.js b/www/themes/profind/lib/smartresize/jquery.debouncedresize.js new file mode 100644 index 0000000..5261fbf --- /dev/null +++ b/www/themes/profind/lib/smartresize/jquery.debouncedresize.js @@ -0,0 +1,47 @@ +/* + * debouncedresize: special jQuery event that happens once after a window resize + * + * latest version and complete README available on Github: + * https://github.com/louisremi/jquery-smartresize + * + * Copyright 2012 @louis_remi + * Licensed under the MIT license. + * + * This saved you an hour of work? + * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON + */ +(function($) { + +var $event = $.event, + $special, + resizeTimeout; + +$special = $event.special.debouncedresize = { + setup: function() { + $( this ).on( "resize", $special.handler ); + }, + teardown: function() { + $( this ).off( "resize", $special.handler ); + }, + handler: function( event, execAsap ) { + // Save the context + var context = this, + args = arguments, + dispatch = function() { + // set correct event type + event.type = "debouncedresize"; + $event.dispatch.apply( context, args ); + }; + + if ( resizeTimeout ) { + clearTimeout( resizeTimeout ); + } + + execAsap ? + dispatch() : + resizeTimeout = setTimeout( dispatch, $special.threshold ); + }, + threshold: 150 +}; + +})(jQuery); \ No newline at end of file diff --git a/www/themes/profind/lib/smartresize/jquery.throttledresize.js b/www/themes/profind/lib/smartresize/jquery.throttledresize.js new file mode 100644 index 0000000..4ba4a86 --- /dev/null +++ b/www/themes/profind/lib/smartresize/jquery.throttledresize.js @@ -0,0 +1,58 @@ +/* + * throttledresize: special jQuery event that happens at a reduced rate compared to "resize" + * + * latest version and complete README available on Github: + * https://github.com/louisremi/jquery-smartresize + * + * Copyright 2012 @louis_remi + * Licensed under the MIT license. + * + * This saved you an hour of work? + * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON + */ +(function($) { + +var $event = $.event, + $special, + dummy = {_:0}, + frame = 0, + wasResized, animRunning; + +$special = $event.special.throttledresize = { + setup: function() { + $( this ).on( "resize", $special.handler ); + }, + teardown: function() { + $( this ).off( "resize", $special.handler ); + }, + handler: function( event, execAsap ) { + // Save the context + var context = this, + args = arguments; + + wasResized = true; + + if ( !animRunning ) { + setInterval(function(){ + frame++; + + if ( frame > $special.threshold && wasResized || execAsap ) { + // set correct event type + event.type = "throttledresize"; + $event.dispatch.apply( context, args ); + wasResized = false; + frame = 0; + } + if ( frame > 9 ) { + $(dummy).stop(); + animRunning = false; + frame = 0; + } + }, 30); + animRunning = true; + } + }, + threshold: 0 +}; + +})(jQuery); \ No newline at end of file diff --git a/www/themes/profind/views/candidato/_form.php b/www/themes/profind/views/candidato/_form.php new file mode 100644 index 0000000..5285a6f --- /dev/null +++ b/www/themes/profind/views/candidato/_form.php @@ -0,0 +1,296 @@ +clientScript->registerScriptFile(Yii::app()->theme->baseUrl . '/js/bootstrap-inputmask.js'); ?> +clientScript->registerScriptFile(Yii::app()->theme->baseUrl . '/js/bootstrap-fileupload.js'); ?> +clientScript->registerScriptFile(Yii::app()->theme->baseUrl . '/lib/chosen/chosen.jquery.min.js'); ?> + +clientScript->registerCssFile(Yii::app()->theme->baseUrl . '/lib/chosen/chosen.css'); ?> + +clientScript->registerScript('js_chosen', $js_chosen, CClientScript::POS_END); + +$js_quitar_foto = <<clientScript->registerScript('js_quitar_foto', $js_quitar_foto, CClientScript::POS_END); + +$js_init = <<clientScript->registerScript('js_init', $js_init, CClientScript::POS_END); +?> + +beginWidget('CActiveForm', array( + 'id' => 'candidato-form', + 'enableAjaxValidation' => false, + 'htmlOptions' => array( + 'enctype' => 'multipart/form-data', + 'class' => 'form-horizontal' + ) + )); +?> + +
    +
    + hasErrors()) { ?> +
    + × + ' . Yii::t('profind', 'Se han encontrado errores') . '', '', array('firstError' => true)); + ?> +
    + +
    +
    + +
    + +
    +
    +
    + labelEx($candidato, 'n_identificacion', array('class' => 'control-label')); ?> +
    + textField($candidato, 'n_identificacion', array('class' => 'span6')); ?> +
    +
    +
    + labelEx($candidato, 'nombre', array('class' => 'control-label')); ?> +
    + textField($candidato, 'nombre', array('class' => 'span12')); ?> +
    +
    +
    + labelEx($candidato, 'apellidos', array('class' => 'control-label')); ?> +
    + textField($candidato, 'apellidos', array('class' => 'span12')); ?> +
    +
    +
    + labelEx($candidato, 'sexo', array('class' => 'control-label')); ?> +
    + + +
    +
    +
    + labelEx($candidato, 'fecha_nacimiento', array('class' => 'control-label')); ?> +
    + widget('zii.widgets.jui.CJuiDatePicker', array( + 'model' => $candidato, + 'attribute' => 'fecha_nacimiento', + 'language' => 'es', + 'options' => array('showAnim' => 'fold'), + 'htmlOptions' => array('class' => 'span6'), + )); + ?> +
    +
    +
    + labelEx($candidato, 'lugar_nacimiento', array('class' => 'control-label')); ?> +
    + findAll(), 'id', 'poblacion'); + echo $form->dropDownList($candidato, 'lugar_nacimiento', $lista, array( + 'empty' => '', + 'data-placeholder' => Yii::t('profind', 'Elegir la localidad...'), + 'class' => 'span6 localidad', + )); + ?> +
    +
    +
    +
    +
    +
    + +
    + +
    +
    + labelEx($candidato, 'email', array('class' => 'control-label')); ?> +
    +
    + + textField($candidato, 'email', array('class' => 'span12')); ?> +
    +
    +
    +
    +
    +
    + labelEx($candidato, 'telefono_fijo', array('class' => 'control-label')); ?> +
    + textField($candidato, 'telefono_fijo', array('class' => 'span12')); ?> +
    +
    +
    + labelEx($candidato, 'telefono_movil', array('class' => 'control-label')); ?> +
    + textField($candidato, 'telefono_movil', array('class' => 'span12')); ?> +
    +
    +
    +
    + + +
    + +
    +
    +
    + +
    + textField($candidato, 'disponibilidad_incorporacion', array('class' => 'span12')); ?> +
    +
    +
    + +
    + textField($candidato, 'disponibilidad_entrevistas', array('class' => 'span12')); ?> +
    +
    +
    + +
    + textField($candidato, 'disponibilidad_guardias', array('class' => 'span12')); ?> +
    +
    +
    +
    +
    + +
    + textField($candidato, 'disponibilidad_viajar', array('class' => 'span12')); ?> +
    +
    +
    + +
    + textField($candidato, 'disponibilidad_proyectos_internacionales', array('class' => 'span12')); ?> +
    +
    +
    +
    +
    + +
    +
    +
    + + +
    +
    + salario_minimo; ?> € - salario_maximo; ?>€ +
    + widget('zii.widgets.jui.CJuiSliderInput', array( + 'model' => $candidato, + 'attribute' => 'salario_minimo', + 'maxAttribute' => 'salario_maximo', + 'event' => 'change', + 'options' => array( + 'range' => true, + 'step'=> 1000, + 'min' => Yii::app()->params['salarios_candidatos']['salario_minimo'], + 'max' =>Yii::app()->params['salarios_candidatos']['salario_maximo'], + 'slide' => 'js:function(event,ui){$("#salario_min").text(ui.values[0]); $("#salario_max").text(ui.values[1]);}', + ), + 'htmlOptions' => array('class' => 'sepH_b'), + )); + ?> +
    +
    +
    +
    + +
    +
    +
    +
    + labelEx($candidato, 'carnet_conducir', array('class' => 'control-label')); ?> +
    + textField($candidato, 'carnet_conducir', array('class' => 'span12')); ?> +
    +
    +
    +
    + labelEx($candidato, 'vehiculo_propio', array('class' => 'control-label')); ?> +
    + textField($candidato, 'vehiculo_propio', array('class' => 'span12')); ?> +
    +
    +
    +
    + +
    +
    +
    + labelEx($candidato, 'observaciones', array('class' => 'control-label')); ?> +
    + textArea($candidato, 'observaciones', array('class' => 'span12', 'rows' => 5)); ?> +
    +
    +
    +
    + +
    + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + +endWidget(); ?> diff --git a/www/themes/profind/views/candidato/_grid.php b/www/themes/profind/views/candidato/_grid.php new file mode 100644 index 0000000..98223af --- /dev/null +++ b/www/themes/profind/views/candidato/_grid.php @@ -0,0 +1,238 @@ +clientScript->registerScriptFile(Yii::app()->theme->baseUrl . '/lib/datatables/js/jquery.dataTables.min.js', CClientScript::POS_END); ?> +clientScript->registerScriptFile(Yii::app()->theme->baseUrl . '/lib/datatables/extras/Scroller/media/js/Scroller.min.js', CClientScript::POS_END); ?> + +clientScript->registerCssFile(Yii::app()->theme->baseUrl . '/css/grid.css'); ?> + +clientScript->registerScript('init_grid', ' + $(document).ready(function() { + + $row = $("
    "); + $row.appendTo("#candidato-grid"); + + $column1 = $("
    "); + $column2 = $("
    "); + $column1.appendTo($row); + $column2.appendTo($row); + + $column1.append($("#candidato-grid .dataTables_info")); + $column2.append($("#candidato-grid .pagination")); + + $("#candidato-grid table").dataTable({ + "aaSorting": [[ 2, "asc" ]], + //"bProcessing": true, + //"bServerSide": true, + //"sDom": "<\'row\'<\'span6\'l><\'span6\'f>r>t<\'row\'<\'span6\'i><\'span6\'p>>", + }); + });' +); +?> + + Yii::t('intranet', 'Acciones'), + 'class' => 'CButtonColumn', + 'headerHtmlOptions' => array( + 'style' => 'width:55px;', + 'class' => '', + ), + 'template' => '{update}{delete}', + ), +// array( +// 'type' => 'html', +// 'name' => 'email', +// 'value' => 'CHtml::mailto(CHtml::encode($data->email));', +// 'headerHtmlOptions' => array( +// 'class' => '', +// ), +// 'cssClassExpression' => '', +// ), +); + +$gridView = $this->widget('zii.widgets.grid.CGridView', array( + 'id' => 'candidato-grid', + 'dataProvider' => $candidatos->search(), + 'columns' => $columnas, + 'filter' => $candidatos, + 'filterPosition' => 'footer', + 'cssFile' => false, + 'htmlOptions' => array('class' => 'dataTables_wrapper form-inline'), + 'itemsCssClass' => 'table table-striped table-bordered dataTable', + 'template' => '{items}{summary}{pager}', + 'emptyText' => Yii::t('profind', 'No hay candidatos'), + 'summaryCssClass' => 'dataTables_info', + //'summaryText' => Yii::t('profind', 'Mostrando registros del {start} al {end} de {count} en total.'), + 'pagerCssClass' => 'dataTables_paginate paging_bootstrap_alt pagination', + 'pager' => array( + 'htmlOptions' => array('class' => ''), + 'header' => '', + 'hiddenPageCssClass' => 'disabled', + //'cssFile' =>Yii::app()->theme->baseUrl."/css/style-of-pager.css", + ), + ), true); +?> + + +
    +
    + +
    +
    + + + +
    +
    +
    +
    +
    + + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ImageNameSizeDateActions
    + + + + Lorem ipsum dolor sit
    Image10.jpg
    200 KB28/06/2012 + + + +
    + + + + Lorem ipsum dolor sit
    Image11.jpg
    210 KB27/06/2012 + + + +
    + + + + Lorem ipsum dolor sit
    Image12.jpg
    360 KB25/06/2012 + + + +
    + + + + Lorem ipsum dolor sit
    Image13.jpg
    215 KB24/06/2012 + + + +
    + + + + Lorem ipsum dolor sit
    Image14.jpg
    650 KB24/06/2012 + + + +
    + + + + Lorem ipsum dolor sit
    Image15.jpg
    428 KB23/06/2012 + + + +
    +
    +
    +
    Showing 1 to 6 of 6 entries
    + +
    +
    + +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/www/themes/profind/views/candidato/create.php b/www/themes/profind/views/candidato/create.php new file mode 100644 index 0000000..f830b67 --- /dev/null +++ b/www/themes/profind/views/candidato/create.php @@ -0,0 +1,18 @@ +pageTitle = Yii::t('profind', 'Nuevo candidato'); + + $this->breadcrumbs = array( + Yii::t('profind', 'BD Candidatos') => array('/candidato/index'), + ); + + // Sidebar + //echo $this->renderPartial('//sidebars/_menu_candidato'); + +?> +
    +
    +

    + renderPartial('_form', array('candidato' => $candidato)); ?> +
    +
    diff --git a/www/themes/profind/views/candidato/index.php b/www/themes/profind/views/candidato/index.php new file mode 100644 index 0000000..c33f081 --- /dev/null +++ b/www/themes/profind/views/candidato/index.php @@ -0,0 +1,24 @@ +pageTitle = Yii::t('profind', 'BD Candidatos'); + + $this->breadcrumbs = array( + Yii::t('profind', 'BD Candidatos'), + ); + + // Sidebar + //echo $this->renderPartial('//sidebars/_menu_candidato'); + + // Contenido + //echo $this->renderPartial('_form', array('model' => $model)); + +?> + +
    +
    +

    +
    +
    + +renderPartial('_grid', array('candidatos' => $candidatos)); ?> + diff --git a/www/themes/profind/views/candidato/update.php b/www/themes/profind/views/candidato/update.php new file mode 100644 index 0000000..8aa49f0 --- /dev/null +++ b/www/themes/profind/views/candidato/update.php @@ -0,0 +1,18 @@ +pageTitle = Yii::t('profind', 'Modificación de candidato'); + + $this->breadcrumbs = array( + Yii::t('profind', 'BD Candidatos') => array('/candidato/index'), + ); + + // Sidebar + //echo $this->renderPartial('//sidebars/_menu_candidato'); + +?> +
    +
    +

    nombreCompleto; ?>

    + renderPartial('_form', array('candidato' => $candidato)); ?> +
    +
    diff --git a/www/themes/profind/views/layouts/main.php b/www/themes/profind/views/layouts/main.php index ee673ef..a64bbdb 100644 --- a/www/themes/profind/views/layouts/main.php +++ b/www/themes/profind/views/layouts/main.php @@ -6,9 +6,6 @@ <?php echo CHtml::encode($this->pageTitle); ?> - - - @@ -16,6 +13,9 @@ + + + @@ -24,20 +24,19 @@ - - +