1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2024-11-29 11:24:11 +01:00

Added files for new contact editor/viewer.

This commit is contained in:
Thomas Tanghus 2012-02-06 07:32:57 +01:00
parent 4841adaa6a
commit ad71a024a1
28 changed files with 5839 additions and 0 deletions

60
ajax/addcontact.php Normal file
View File

@ -0,0 +1,60 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
exit();
}
function debug($msg) {
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
}
foreach ($_POST as $key=>$element) {
debug('_POST: '.$key.'=>'.$element);
}
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$l=new OC_L10N('contacts');
$aid = $_POST['aid'];
$addressbook = OC_Contacts_App::getAddressbook( $aid );
$fn = trim($_POST['fn']);
$n = trim($_POST['n']);
$vcard = new OC_VObject('VCARD');
$vcard->setUID();
$vcard->setString('N',$n);
$vcard->setString('FN',$fn);
$id = OC_Contacts_VCard::add($aid,$vcard->serialize());
if(!$id) {
OC_JSON::error(array('data' => array('message' => $l->t('There was an error adding the contact.'))));
OC_Log::write('contacts','ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OC_Log::ERROR);
exit();
}
OC_JSON::success(array('data' => array( 'id' => $id )));

53
ajax/contactdetails.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/contactdetails.php: '.$msg, OC_Log::DEBUG);
exit();
}
function debug($msg) {
OC_Log::write('contacts','ajax/contactdetails.php: '.$msg, OC_Log::DEBUG);
}
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$l=new OC_L10N('contacts');
$id = $_GET['id'];
$vcard = OC_Contacts_App::getContactVCard( $id );
if(is_null($vcard)) {
bailOut($l->t('Error parsing VCard for ID: "'.$id.'"'));
}
$details = OC_Contacts_VCard::structureContact($vcard);
if(isset($details['PHOTO'])) {
$details['PHOTO'] = true;
//unset($details['PHOTO']);
} else {
$details['PHOTO'] = false;
}
$details['id'] = $id;
OC_JSON::success(array('data' => $details));

38
ajax/cropphoto.php Normal file
View File

@ -0,0 +1,38 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$tmp_path = $_GET['tmp_path'];
$id = $_GET['id'];
OC_Log::write('contacts','ajax/cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
$tmpl = new OC_TEMPLATE("contacts", "part.cropphoto");
$tmpl->assign('tmp_path', $tmp_path);
$tmpl->assign('id', $id);
$page = $tmpl->fetchPage();
OC_JSON::success(array('data' => array( 'page' => $page )));

31
ajax/editaddress.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/**
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
require_once('../../../lib/base.php');
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$id = $_GET['id'];
$checksum = isset($_GET['checksum'])?$_GET['checksum']:'';
$vcard = OC_Contacts_App::getContactVCard($id);
$adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
$tmpl = new OC_TEMPLATE("contacts", "part.edit_address_dialog");
if($checksum) {
$line = OC_Contacts_App::getPropertyLineByChecksum($vcard, $checksum);
$element = $vcard->children[$line];
$adr = OC_Contacts_VCard::structureProperty($element);
$tmpl->assign('adr',$adr);
}
$tmpl->assign('id',$id);
$tmpl->assign('adr_types',$adr_types);
$tmpl->printpage();
?>

35
ajax/editname.php Normal file
View File

@ -0,0 +1,35 @@
<?php
/**
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
require_once('../../../lib/base.php');
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$tmpl = new OC_TEMPLATE("contacts", "part.edit_name_dialog");
$id = $_GET['id'];
if($id) {
$vcard = OC_Contacts_App::getContactVCard($id);
$name = array('', '', '', '', '');
if($vcard->__isset('N')) {
$property = $vcard->__get('N');
if($property) {
$name = OC_Contacts_VCard::structureProperty($property);
}
}
$tmpl->assign('name',$name);
$tmpl->assign('id',$id);
} else {
$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
$tmpl->assign('addressbooks', $addressbooks);
}
$tmpl->printpage();
?>

53
ajax/loadphoto.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* TODO: Translatable strings.
* Remember to delete tmp file at some point.
*/
// Init owncloud
require_once('../../../lib/base.php');
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$l=new OC_L10N('contacts');
// foreach ($_POST as $key=>$element) {
// OC_Log::write('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OC_Log::DEBUG);
// }
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/savecrop.php: '.$msg, OC_Log::DEBUG);
exit();
}
$image = null;
$id = isset($_GET['id']) ? $_GET['id'] : '';
if($id == '') {
bailOut('Missing contact id.');
}
$tmpl = new OC_TEMPLATE("contacts", "part.contactphoto");
$tmpl->assign('id', $id);
$page = $tmpl->fetchPage();
OC_JSON::success(array('data' => array('page'=>$page)));
?>

58
ajax/newcontact.php Normal file
View File

@ -0,0 +1,58 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
exit();
}
function debug($msg) {
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
}
foreach ($_POST as $key=>$element) {
debug('_POST: '.$key.'=>'.$element);
}
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$addressbooks = OC_Contacts_Addressbook::all(OC_USER::getUser());
$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
$freeSpace=OC_Filesystem::free_space('/');
$freeSpace=max($freeSpace,0);
$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
$tmpl = new OC_Template('contacts','part.contact');
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
$tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
$tmpl->assign('addressbooks',$addressbooks);
$tmpl->assign('id','');
$page = $tmpl->fetchPage();
OC_JSON::success(array('data' => array( 'page' => $page )));

136
ajax/savecrop.php Normal file
View File

@ -0,0 +1,136 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* TODO: Translatable strings.
* Remember to delete tmp file at some point.
*/
// Init owncloud
require_once('../../../lib/base.php');
OC_Log::write('contacts','ajax/savecrop.php: Huzzah!!!', OC_Log::DEBUG);
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$l=new OC_L10N('contacts');
// foreach ($_POST as $key=>$element) {
// OC_Log::write('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OC_Log::DEBUG);
// }
// Firefox and Konqueror tries to download application/json for me. --Arthur
OC_JSON::setContentTypeHeader('text/plain');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/savecrop.php: '.$msg, OC_Log::DEBUG);
exit();
}
$image = null;
$x1 = (isset($_POST['x1']) && $_POST['x1']) ? $_POST['x1'] : -1;
//$x2 = isset($_POST['x2']) ? $_POST['x2'] : -1;
$y1 = (isset($_POST['y1']) && $_POST['y1']) ? $_POST['y1'] : -1;
//$y2 = isset($_POST['y2']) ? $_POST['y2'] : -1;
$w = (isset($_POST['w']) && $_POST['w']) ? $_POST['w'] : -1;
$h = (isset($_POST['h']) && $_POST['h']) ? $_POST['h'] : -1;
$tmp_path = isset($_POST['tmp_path']) ? $_POST['tmp_path'] : '';
$id = isset($_POST['id']) ? $_POST['id'] : '';
if(in_array(-1, array($x1, $y1, $w, $h))) {
bailOut('Wrong crop dimensions: '.implode(', ', array($x1, $y1, $w, $h)));
}
if($tmp_path == '') {
bailOut('Missing path to temporary file.');
}
if($id == '') {
bailOut('Missing contact id.');
}
OC_Log::write('contacts','savecrop.php: files: '.$tmp_path.' exists: '.file_exists($tmp_path), OC_Log::DEBUG);
if(file_exists($tmp_path)) {
$image = new OC_Image();
if($image->loadFromFile($tmp_path)) {
if($image->crop($x1, $y1, $w, $h)) {
if($image->resize(200)) {
$tmpfname = tempnam("/tmp", "occCropped"); // create a new file because of caching issues.
if($image->save($tmpfname)) {
unlink($tmp_path);
$card = OC_Contacts_App::getContactVCard($id);
if(!$card) {
unlink($tmpfname);
bailOut('Error getting contact object.');
}
if($card->__isset('PHOTO')) {
OC_Log::write('contacts','savecrop.php: files: PHOTO property exists.', OC_Log::DEBUG);
$property = $card->__get('PHOTO');
if(!$property) {
unlink($tmpfname);
bailOut('Error getting PHOTO property.');
}
$property->setValue($image->__toString());
$property->parameters[] = new Sabre_VObject_Parameter('ENCODING', 'b');
$property->parameters[] = new Sabre_VObject_Parameter('TYPE', $image->mimeType());
$card->__set('PHOTO', $property);
} else {
OC_Log::write('contacts','savecrop.php: files: Adding PHOTO property.', OC_Log::DEBUG);
$card->addProperty('PHOTO', $image->__toString(), array('ENCODING' => 'b', 'TYPE' => $image->mimeType()));
}
if(!OC_Contacts_VCard::edit($id,$card->serialize())) {
bailOut('Error saving contact.');
}
unlink($tmpfname);
//$result=array( "status" => "success", 'mime'=>$image->mimeType(), 'tmp'=>$tmp_path);
$tmpl = new OC_TEMPLATE("contacts", "part.contactphoto");
$tmpl->assign('tmp_path', $tmpfname);
$tmpl->assign('mime', $image->mimeType());
$tmpl->assign('id', $id);
$tmpl->assign('width', $image->width());
$tmpl->assign('height', $image->height());
$page = $tmpl->fetchPage();
OC_JSON::success(array('data' => array('page'=>$page, 'tmp'=>$tmpfname)));
exit();
} else {
if(file_exists($tmpfname)) {
unlink($tmpfname);
}
bailOut('Error saving temporary image');
}
} else {
bailOut('Error resizing image');
}
} else {
bailOut('Error cropping image');
}
} else {
bailOut('Error creating temporary image');
}
} else {
bailOut('Error finding image: '.$tmp_path);
}
if($tmp_path != '' && file_exists($tmp_path)) {
unlink($tmp_path);
}
?>

134
ajax/saveproperty.php Normal file
View File

@ -0,0 +1,134 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Jakob Sack
* @copyright 2011 Jakob Sack mail@jakobsack.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$l=new OC_L10N('contacts');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
exit();
}
function debug($msg) {
OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
}
foreach ($_POST as $key=>$element) {
debug('_POST: '.$key.'=>'.$element);
}
$id = isset($_POST['id'])?$_POST['id']:null;
$name = isset($_POST['name'])?$_POST['name']:null;
$value = isset($_POST['value'])?$_POST['value']:null;
$parameters = isset($_POST['parameters'])?$_POST['parameters']:null;
$checksum = isset($_POST['checksum'])?$_POST['checksum']:null;
// if(!is_null($parameters)) {
// debug('parameters: '.count($parameters));
// foreach($parameters as $key=>$val ) {
// debug('parameter: '.$key.'=>'.implode('/',$val));
// }
// }
if(is_array($value)){ // FIXME: How to strip_tags for compound values?
ksort($value); // NOTE: Important, otherwise the compound value will be set in the order the fields appear in the form!
$value = OC_VObject::escapeSemicolons($value);
} else {
$value = trim(strip_tags($value));
}
if(!$id) {
bailOut($l->t('id is not set.'));
}
if(!$checksum) {
bailOut($l->t('checksum is not set.'));
}
if(!$name) {
bailOut($l->t('element name is not set.'));
}
$vcard = OC_Contacts_App::getContactVCard( $id );
$line = OC_Contacts_App::getPropertyLineByChecksum($vcard, $checksum);
if(is_null($line)) {
bailOut($l->t('Information about vCard is incorrect. Please reload the page.'.$checksum.' "'.$line.'"'));
}
$element = $vcard->children[$line]->name;
if($element != $name) {
bailOut($l->t('Something went FUBAR. ').$name.' != '.$element);
}
switch($element) {
case 'BDAY':
$date = New DateTime($value);
//$vcard->setDateTime('BDAY', $date, Sabre_VObject_Element_DateTime::DATE);
$value = $date->format(DateTime::ATOM);
case 'FN':
if(!$value) {
// create a method thats returns an alternative for FN.
//$value = getOtherValue();
}
case 'N':
case 'ORG':
case 'NICKNAME':
debug('Setting string:'.$name.' '.$value);
$vcard->setString($name, $value);
break;
case 'EMAIL':
$value = strtolower($value);
case 'TEL':
case 'ADR': // should I delete the property if empty or throw an error?
debug('Setting element: (EMAIL/TEL/ADR)'.$element);
if(!$value) {
unset($vcard->children[$line]); // Should never happen...
} else {
$vcard->children[$line]->setValue($value);
$vcard->children[$line]->parameters = array();
if(!is_null($parameters)) {
debug('Setting parameters: '.$parameters);
foreach($parameters as $key => $parameter) {
debug('Adding parameter: '.$key);
foreach($parameter as $val) {
debug('Adding parameter: '.$key.'=>'.$val);
$vcard->children[$line]->add(new Sabre_VObject_Parameter($key, strtoupper($val)));
}
}
}
}
break;
}
// Do checksum and be happy
$checksum = md5($vcard->children[$line]->serialize());
debug('New checksum: '.$checksum);
if(!OC_Contacts_VCard::edit($id,$vcard->serialize())) {
OC_JSON::error(array('data' => array('message' => $l->t('Error updating contact property.'))));
OC_Log::write('contacts','ajax/setproperty.php: Error updating contact property: '.$value, OC_Log::ERROR);
exit();
}
//$adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
//$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
OC_JSON::success(array('data' => array( 'line' => $line, 'checksum' => $checksum, 'oldchecksum' => $_POST['checksum'] )));

133
ajax/uploadphoto.php Normal file
View File

@ -0,0 +1,133 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Thomas Tanghus
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../../lib/base.php');
// Check if we are a user
// Firefox and Konqueror tries to download application/json for me. --Arthur
OC_JSON::setContentTypeHeader('text/plain');
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
function bailOut($msg) {
OC_JSON::error(array('data' => array('message' => $msg)));
OC_Log::write('contacts','ajax/uploadphoto.php: '.$msg, OC_Log::DEBUG);
exit();
}
function debug($msg) {
OC_Log::write('contacts','ajax/uploadphoto.php: '.$msg, OC_Log::DEBUG);
}
// foreach ($_SERVER as $key=>$element) {
// debug('$_SERVER: '.$key.'=>'.$element);
// }
// foreach ($_GET as $key=>$element) {
// debug('_GET: '.$key.'=>'.$element);
// }
// foreach ($_POST as $key=>$element) {
// debug('_POST: '.$key.'=>'.$element);
// }
// foreach ($_FILES as $key=>$element) {
// debug('_FILES: '.$key.'=>'.$element);
// }
// If it is a Drag'n'Drop transfer it's handled here.
$fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false);
if ($fn) {
// AJAX call
if (!isset($_GET['id'])) {
OC_Log::write('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OC_Log::DEBUG);
OC_JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
exit();
}
$id = $_GET['id'];
$tmpfname = tempnam('/tmp', 'occOrig');
file_put_contents($tmpfname, file_get_contents('php://input'));
debug($tmpfname.' uploaded');
$image = new OC_Image();
if($image->loadFromFile($tmpfname)) {
if($image->width() > 400 || $image->height() > 400) {
$image->resize(400); // Prettier resizing than with browser and saves bandwidth.
}
if(!$image->fixOrientation()) { // No fatal error so we don't bail out.
debug('Couldn\'t save correct image orientation: '.$tmpfname);
}
if($image->save($tmpfname)) {
OC_JSON::success(array('data' => array('mime'=>$_SERVER['CONTENT_TYPE'], 'name'=>$fn, 'id'=>$id, 'tmp'=>$tmpfname)));
exit();
} else {
bailOut('Couldn\'t save temporary image: '.$tmpfname);
}
} else {
bailOut('Couldn\'t load temporary image: '.$file['tmp_name']);
}
}
if (!isset($_POST['id'])) {
OC_Log::write('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OC_Log::DEBUG);
OC_JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
exit();
}
if (!isset($_FILES['imagefile'])) {
OC_Log::write('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OC_Log::DEBUG);
OC_JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' )));
exit();
}
$error = $_FILES['imagefile']['error'];
if($error !== UPLOAD_ERR_OK) {
$l=new OC_L10N('contacts');
$errors = array(
0=>$l->t("There is no error, the file uploaded with success"),
1=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
2=>$l->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
3=>$l->t("The uploaded file was only partially uploaded"),
4=>$l->t("No file was uploaded"),
6=>$l->t("Missing a temporary folder")
);
bailOut($errors[$error]);
}
$file=$_FILES['imagefile'];
$tmpfname = tempnam("/tmp", "occOrig");
if(file_exists($file['tmp_name'])) {
$image = new OC_Image();
if($image->loadFromFile($file['tmp_name'])) {
if($image->width() > 400 || $image->height() > 400) {
$image->resize(400); // Prettier resizing than with browser and saves bandwidth.
}
if(!$image->fixOrientation()) { // No fatal error so we don't bail out.
debug('Couldn\'t save correct image orientation: '.$tmpfname);
}
if($image->save($tmpfname)) {
OC_JSON::success(array('data' => array('mime'=>$file['type'],'size'=>$file['size'],'name'=>$file['name'], 'id'=>$_POST['id'], 'tmp'=>$tmpfname)));
exit();
} else {
bailOut('Couldn\'t save temporary image: '.$tmpfname);
}
} else {
bailOut('Couldn\'t load temporary image: '.$file['tmp_name']);
}
} else {
bailOut('Temporary file: \''.$file['tmp_name'].'\' has gone AWOL?');
}
?>

60
contacts.php Normal file
View File

@ -0,0 +1,60 @@
<?php
require_once('../../lib/base.php');
// Check if we are a user
OC_Util::checkLoggedIn();
// Get active address books. This creates a default one if none exists.
$ids = OC_Contacts_Addressbook::activeIds(OC_User::getUser());
$contacts = OC_Contacts_VCard::all($ids);
$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
// Load the files we need
OC_App::setActiveNavigationEntry( 'contacts_index' );
// Load a specific user?
$id = isset( $_GET['id'] ) ? $_GET['id'] : null;
$details = array();
// FIXME: This cannot work..?
if(is_null($id) && count($contacts) > 0) {
$id = $contacts[0]['id'];
}
if(!is_null($id)) {
$vcard = OC_Contacts_App::getContactVCard($id);
$details = OC_Contacts_VCard::structureContact($vcard);
}
$property_types = OC_Contacts_App::getAddPropertyOptions();
$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
$freeSpace=OC_Filesystem::free_space('/');
$freeSpace=max($freeSpace,0);
$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
OC_Util::addScript('','jquery.multiselect');
//OC_Util::addScript('contacts','interface');
OC_Util::addScript('contacts','contacts');
OC_Util::addScript('contacts','jquery.inview');
OC_Util::addScript('contacts','jquery.Jcrop');
OC_Util::addScript('contacts','jquery.jec-1.3.3');
OC_Util::addStyle('','jquery.multiselect');
//OC_Util::addStyle('contacts','styles');
OC_Util::addStyle('contacts','jquery.Jcrop');
OC_Util::addStyle('contacts','contacts');
$tmpl = new OC_Template( "contacts", "index2", "user" );
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
$tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
$tmpl->assign('property_types',$property_types);
$tmpl->assign('phone_types',$phone_types);
$tmpl->assign('addressbooks', $addressbooks);
$tmpl->assign('contacts', $contacts);
$tmpl->assign('details', $details );
$tmpl->assign('id',$id);
$tmpl->printPage();
?>

BIN
css/Jcrop.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

213
css/contacts.css Normal file
View File

@ -0,0 +1,213 @@
/*dl > dt {
font-weight: bold;
}*/
#contacts { padding-left:2px; padding-top: 5px; background: #fff; }
#leftcontent a { height: 23px; display: block; margin: 0 0 0 0; padding: 0 0 0 25px; }
#chooseaddressbook {margin-right: 170px; float: right;}
#contacts_deletecard {position:absolute;top:15px;right:25px;}
#contacts_downloadcard {position:absolute;top:15px;right:50px;}
#contacts_propertymenu_button { position:absolute;top:15px;right:150px; height: 20px; width: 150px; background:url('../../../core/img/actions/add.svg') no-repeat center; }
#contacts_propertymenu { position:absolute;top:35px;right:150px; -moz-border-radius:0.5em; -webkit-border-radius:0.5em; border-radius:0.5em; -moz-border-radius:0.5em; -webkit-border-radius:0.5em; border-radius:0.5em; }
#contacts_propertymenu li { display: block; font-weight: bold; border-left: thin solid #1d2d44; border-right: thin solid #1d2d44; height: 20px; width: 100px; }
#contacts_propertymenu li:first-child { border-top: thin solid #1d2d44; -moz-border-radius-topleft:0.5em; -webkit-border-top-left-radius:0.5em; border-top-left-radius:0.5em; -moz-border-radius-topright:0.5em; -webkit-border-top-right-radius:0.5em; border-top-right-radius:0.5em; }
#contacts_propertymenu li:last-child { border-bottom: thin solid #1d2d44; -moz-border-radius-bottomleft:0.5em; -webkit-border-bottom-left-radius:0.5em; border-bottom-left-radius:0.5em; -moz-border-radius-bottomright:0.5em; -webkit-border-bottom-right-radius:0.5em; border-bottom-right-radius:0.5em; }
#contacts_propertymenu li a { padding: 3px; display: block }
#contacts_propertymenu li:hover { background-color: #1d2d44; }
#contacts_propertymenu li a:hover { color: #fff }
#actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0;}
#card { /*max-width: 70em;*/ border: thin solid lightgray; display: block; }
#firstrun { /*border: thin solid lightgray;*/ width: 80%; margin: 5em auto auto auto; text-align: center; font-weight:bold; font-size:1.5em; color:#777;}
#firstrun #selections { /*border: thin solid lightgray;*/ font-size:0.8em; width: 100%; margin: 2em auto auto auto; clear: both; }
#card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select { background-color: #f8f8f8; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; }
#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; }
input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid { background-color: #ffc0c0 !important; }
/*input[type="text"]:valid,input[type="email"]:valid,input[type="tel"]:valid,input[type="date"]:valid { background-color: #b1d28f !important; }*/
dl.form
{
width: 100%;
float: left;
clear: right;
margin: 0;
padding: 0;
}
.form dt
{
display: table-cell;
clear: left;
float: left;
width: 7em;
/*overflow: hidden;*/
margin: 0;
padding: 0.8em 0.5em 0 0;
font-weight: bold;
text-align:right;
text-overflow:ellipsis;
o-text-overflow: ellipsis;
vertical-align: text-bottom;
/*
white-space: pre-wrap;
white-space: -moz-pre-wrap !important;
white-space: -pre-wrap;
white-space: -o-pre-wrap;*/
}
.form dd
{
display: table-cell;
clear: right;
float: left;
margin: 0;
padding: 0px;
white-space: nowrap;
vertical-align: text-bottom;
/*min-width: 20em;*/
/*background-color: yellow;*/
}
.loading { background: url('../../../core/img/loading.gif') no-repeat center !important;}
/*.add { cursor: pointer; width: 25px; height: 25px; margin: 0px; float: right; position:relative; content: "\+"; font-weight: bold; color: #666; font-size: large; bottom: 0px; right: 0px; clear: both; text-align: center; vertical-align: bottom; display: none; }*/
.listactions { height: 1em; width:60px; float: left; clear: right; }
.add,.edit,.delete,.mail, .globe { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; display: none; }
.add { background:url('../../../core/img/actions/add.svg') no-repeat center; clear: both; }
.delete { background:url('../../../core/img/actions/delete.svg') no-repeat center; }
.edit { background:url('../../../core/img/actions/rename.svg') no-repeat center; }
.mail { background:url('../../../core/img/actions/mail.svg') no-repeat center; }
.globe { background:url('../img/globe.svg') no-repeat center; }
#messagebox_msg { font-weight: bold; font-size: 1.2em; }
/* Name editor */
#edit_name_dialog {
/*width: 25em;*/
padding:0;
}
#edit_name_dialog > input {
width: 15em;
}
/* Address editor */
#edit_address_dialog {
/*width: 30em;*/
}
#edit_address_dialog > input {
width: 15em;
}
#edit_photo_dialog_img {
display: block;
width: 150;
height: 200;
border: thin solid black;
}
#fn {
float: left;
}
.jecEditableOption {
margin: 2px;
border-radius: 0.5em;
border: thin solid #bbb;
content: 'Custom';
}
/**
* Create classes form, floateven and floatodd which flows left and right respectively.
*/
.contactsection {
float: left;
min-width: 30em;
max-width: 40em;
margin: 0.5em;
border: thin solid lightgray;
-webkit-border-radius: 0.5em;
-moz-border-radius: 0.5em;
border-radius: 0.5em;
background-color: #f8f8f8;
}
.contactpart legend {
/*background: #fff;
font-weight: bold;
left: 1em;
border: thin solid gray;
-webkit-border-radius: 0.5em;
-moz-border-radius: 0.5em;
border-radius: 0.5em;
padding: 3px;*/
width:auto; padding:.3em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em;
}
/*#contacts_details_photo {
cursor: pointer;
z-index:1;
margin: auto;
}
*/
#cropbox {
margin: auto;
}
/* Photo editor */
/*#contacts_details_photo_wrapper {
z-index: 1000;
}*/
#contacts_details_photo {
border-radius: 0.5em;
border: thin solid #bbb;
padding: 0.5em;
margin: 1em 1em 1em 7em;
cursor: pointer;
/*background: #f8f8f8;*/
background: url(../../../core/img/loading.gif) no-repeat center center;
clear: right;
}
#contacts_details_photo:hover {
background: #fff;
}
#contacts_details_photo_progress {
margin: 0.3em 0.3em 0.3em 7em;
clear: left;
}
/* Address editor */
#addressdisplay { padding: 0.5em; }
dl.addresscard { background-color: #fff; float: left; width: 45%; margin: 0 0.3em 0.3em 0.3em; padding: 0; border: thin solid lightgray; }
dl.addresscard dd {}
dl.addresscard dt { padding: 0.3em; border-bottom: thin solid lightgray; font-weight: bold; clear: both;}
dl.addresscard dd > ul { margin: 0.3em; padding: 0.3em; }
#adr_type {} /* Select */
#adr_pobox {}
#adr_extended {}
#adr_street {}
#adr_city {}
#adr_region {}
#adr_zipcode {}
#adr_country {}
.delimiter {
height: 10px;
clear: both;
}
.updatebar {
height: 30px;
clear: both;
padding-right: 170px;
border: thin solid lightgray;
}
.updatebar button {
float: left; margin: 1em;
}
/*input[type="text"] { float: left; max-width: 15em; }
input[type="radio"] { float: left; -khtml-appearance: none; width: 20px; height: 20px; vertical-align: middle; }*/
#file_upload_target, #crop_target { display:none; }
#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; position:absolute; left:0; top:0; cursor:pointer; width:0; height:0;}
input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; }
.propertycontainer dd { float: left; width: 25em; }
.propertylist { clear: none; max-width: 28em; }
.propertylist li { /*background-color: cyan; */ min-width: 25em; /*max-width: 30em;*/ display: block; clear: right; }
.propertylist li > input[type="text"],input[type="email"],input[type="tel"] { float: left; max-width: 15em; }
.propertylist li > input[type="checkbox"],input[type="radio"] { float: left; clear: left; width: 20px; height: 20px; vertical-align: middle; }
.propertylist li > select { float: left; max-width: 8em; }
.typelist { float: left; max-width: 10em; } /* for multiselect */
.addresslist { clear: both; }

84
css/jquery.Jcrop.css Normal file
View File

@ -0,0 +1,84 @@
/* jquery.Jcrop.css
The code contained in this file is free software under MIT License
Copyright (c)2008-2011 Tapmodo Interactive LLC
*/
/*
The outer-most container in a typical Jcrop instance
If you are having difficulty with formatting related to styles
on a parent element, place any fixes here or in a like selector
*/
.jcrop-holder {
direction: ltr;
text-align: left;
}
.jcrop-vline, .jcrop-hline {
background: white url('Jcrop.gif') top left repeat;
font-size: 0px;
position: absolute;
}
.jcrop-vline {
height: 100%;
width: 1px !important;
}
.jcrop-hline {
width: 100%;
height: 1px !important;
}
.jcrop-vline.right {
right: 0px;
}
.jcrop-hline.bottom {
bottom: 0px;
}
.jcrop-handle {
background-color: #333;
border: 1px #eee solid;
font-size: 1px;
}
.jcrop-tracker {
height: 100%;
-webkit-tap-highlight-color: transparent; /* "turn off" link highlight */
-webkit-touch-callout: none; /* disable callout, image save panel */
-webkit-user-select: none; /* disable cut copy paste */
width: 100%;
}
/*
*/
.jcrop-light .jcrop-vline, .jcrop-light .jcrop-hline {
background: white;
filter: Alpha(opacity=70) !important;
opacity: .70 !important;
}
.jcrop-light .jcrop-handle {
background-color: black;
border-color: white;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
.jcrop-dark .jcrop-vline, .jcrop-dark .jcrop-hline {
background: black;
filter: Alpha(opacity=70) !important;
opacity: 0.70 !important;
}
.jcrop-dark .jcrop-handle {
background-color: white;
border-color: black;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}

35
dynphoto.php Normal file
View File

@ -0,0 +1,35 @@
<?php
/**
* ownCloud - Image generator for contacts.
*
* @author Thomas Tanghus
* @copyright 2011 Thomas Tanghus <thomas@tanghus.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../lib/base.php');
$tmp_path = $_GET['tmp_path'];
$maxsize = isset($_GET['maxsize']) ? $_GET['maxsize'] : -1;
header("Cache-Control: no-cache, no-store, must-revalidate");
OC_Log::write('contacts','dynphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
$image = new OC_Image($tmp_path);
if($maxsize != -1) {
$image->resize($maxsize);
}
$image();

102
img/globe.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

BIN
img/person_large.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

1289
js/contacts.js Normal file
View File

@ -0,0 +1,1289 @@
function ucwords (str) {
return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
return $1.toUpperCase();
});
}
String.prototype.strip_tags = function(){
tags = this;
stripped = tags.replace(/[\<\>]/gi, "");
return stripped;
}
Contacts={
UI:{
notImplemented:function() {
Contacts.UI.messageBox(t('contacts', 'Not implemented'), t('contacts', 'Sorry, this functionality has not been implemented yet'));
},
searchOSM:function(obj) {
var adr = Contacts.UI.propertyContainerFor(obj).find('.adr').val();
console.log('adr 1: ' + adr);
if(adr == undefined) {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', 'Couldn\'t get a valid address.'));
return;
}
// FIXME: I suck at regexp. /Tanghus
var adrarr = adr.split(';');
var adrstr = '';
if(adrarr[2].trim() != '') {
adrstr = adrstr + adrarr[2].trim() + ',';
}
if(adrarr[3].trim() != '') {
adrstr = adrstr + adrarr[3].trim() + ',';
}
if(adrarr[4].trim() != '') {
adrstr = adrstr + adrarr[4].trim() + ',';
}
if(adrarr[5].trim() != '') {
adrstr = adrstr + adrarr[5].trim() + ',';
}
if(adrarr[6].trim() != '') {
adrstr = adrstr + adrarr[6].trim();
}
console.log('adrstr: "' + adrstr + '"');
adrstr = encodeURIComponent(adrstr);
console.log('adrstr 2: ' + adrstr);
var uri = 'http://open.mapquestapi.com/nominatim/v1/search.php?q=' + adrstr + '&limit=10&addressdetails=1&zoom=';
console.log('uri: ' + uri);
var newWindow = window.open(uri,'_blank');
newWindow.focus();
//Contacts.UI.notImplemented();
},
mailTo:function(obj) {
var adr = Contacts.UI.propertyContainerFor($(obj)).find('input[type="email"]').val().trim();
if(adr == '') {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', 'Please enter an email address.'));
return;
}
window.location.href='mailto:' + adr;
},
propertyContainerFor:function(obj) {
return $(obj).parents('.propertycontainer').first();
},
checksumFor:function(obj) {
return $(obj).parents('.propertycontainer').first().data('checksum');
},
propertyTypeFor:function(obj) {
return $(obj).parents('.propertycontainer').first().data('element');
},
checkListFor:function(obj) {
var type = $(obj).parents('.propertycontainer').first().data('element');
console.log('checkListFor: ' + type);
switch (type) {
case 'EMAIL':
console.log('emails: '+$('#emaillist>li').length);
if($('#emaillist>li').length == 1) {
$('#emails').hide();
}
break;
case 'TEL':
console.log('phones: '+$('#phonelist>li').length);
if($('#phonelist>li').length == 1) {
$('#phones').hide();
}
break;
case 'ADR':
console.log('addresses: '+$('#addressdisplay>dl').length);
if($('#addressdisplay>dl').length == 1) {
$('#addresses').hide();
}
break;
case 'NICKNAME':
case 'ORG':
case 'BDAY':
break;
}
},
loading:function(obj, state) {
if(state) {
$(obj).addClass('loading');
} else {
$(obj).removeClass('loading');
}
},
showCardDAVUrl:function(username, bookname){
$('#carddav_url').val(totalurl + '/' + username + '/' + bookname);
$('#carddav_url').show();
$('#carddav_url_close').show();
},
messageBox:function(title, msg) {
//alert(msg);
if($('#messagebox').dialog('isOpen') == true){
// NOTE: Do we ever get here?
$('#messagebox').dialog('moveToTop');
}else{
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'messagebox.php'), function(){
$('#messagebox').dialog(
{
autoOpen: true,
title: title,
buttons: [{
text: "Ok",
click: function() { $(this).dialog("close"); }
}],
close: function(event, ui) {
$(this).dialog('destroy').remove();
},
open: function(event, ui) {
$('#messagebox_msg').html(msg);
}
});
});
}
},
loadListHandlers:function() {
//$('.add,.delete').hide();
$('.globe,.mail,.delete,.edit').tipsy();
$('.addresscard,.propertylist li,.propertycontainer').hover(
function () {
$(this).find('.globe,.mail,.delete,.edit').fadeIn(100);
},
function () {
$(this).find('.globe,.mail,.delete,.edit').fadeOut(100);
}
);
},
loadHandlers:function() {
console.log('loadHandlers');
/*
$('.formfloat').hover(
function () {
$(this).find('.add').fadeIn(500);
},
function () {
$(this).find('.add').fadeOut(500);
}
);*/
$('#contacts_deletecard').tipsy({gravity: 'ne'});
$('#contacts_downloadcard').tipsy({gravity: 'ne'});
$('.button').tipsy();
$('#fn').jec();
$('.jecEditableOption').attr('title', t('contacts','Custom'));
$('#fn').tipsy();
$('#contacts_details_photo_wrapper').tipsy();
$('#bday').datepicker({
dateFormat : 'dd-mm-yy'
});
// Style phone types
$('#phonelist').find('select[class*="contacts_property"]').multiselect({
noneSelectedText: t('contacts', 'Select type'),
header: false,
selectedList: 4,
classes: 'typelist'
});
$('#add_email').click(function(){
Contacts.UI.Card.addMail();
});
$('#add_phone').click(function(){
Contacts.UI.Card.addPhone();
});
// $('#add_address').click(function(){
// Contacts.UI.Card.editAddress();
// return false;
// });
$('#n').click(function(){
Contacts.UI.Card.editName();
//return false;
});
$('#edit_name').click(function(){
Contacts.UI.Card.editName();
return false;
});
/* Initialize the photo edit dialog */
$('#edit_photo_dialog').dialog({ autoOpen: false, modal: true, height: 'auto', width: 'auto' });
$('#edit_photo_dialog' ).dialog( 'option', 'buttons', [
{
text: "Ok",
click: function() {
Contacts.UI.Card.savePhoto(this);
$(this).dialog('close');
}
},
{
text: "Cancel",
click: function() { $(this).dialog('close'); }
}
] );
Contacts.UI.loadListHandlers();
},
Card:{
id:'',
fn:'',
fullname:'',
shortname:'',
famname:'',
givname:'',
addname:'',
honpre:'',
honsuf:'',
data:undefined,
export:function() {
document.location.href = OC.linkTo('contacts', 'export.php') + '?contactid=' + this.id;
//$.get(OC.linkTo('contacts', 'export.php'),{'contactid':this.id},function(jsondata){
//});
},
delete:function() {
$('#contacts_deletecard').tipsy('hide');
$.getJSON('ajax/deletecard.php',{'id':this.id},function(jsondata){
if(jsondata.status == 'success'){
$('#leftcontent [data-id="'+jsondata.data.id+'"]').remove();
$('#rightcontent').data('id','');
//$('#rightcontent').empty();
this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = '';
this.data = undefined;
// Load empty page.
var firstid = $('#contacts li:first-child').data('id');
console.log('trying to load: ' + firstid);
$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':firstid},function(jsondata){
if(jsondata.status == 'success'){
Contacts.UI.Card.loadContact(jsondata.data);
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
}
});
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
//alert(jsondata.data.message);
}
});
return false;
},
loadContact:function(jsondata){
this.data = jsondata;
this.id = this.data.id;
console.log('loaded: ' + this.data.FN[0]['value']);
this.populateNameFields();
this.loadPhoto();
this.loadMails();
this.loadPhones();
this.loadAddresses();
this.loadSingleProperties();
},
loadSingleProperties:function() {
var props = ['BDAY', 'NICKNAME', 'ORG'];
// Clear all elements
$('#ident .propertycontainer[class*="propertycontainer"]').each(function(){
if(props.indexOf($(this).data('element')) > -1) {
// $('#contacts_propertymenu a[data-type="'+$(this).data('element')+'"]').parent().show();
//console.log($(this).html());
$(this).data('checksum', '');
$(this).find('input').val('');
$(this).hide();
$(this).prev().hide();
}
});
for(var prop in props) {
//console.log('loadSingleProperties: ' + props[prop] + ': ' + this.data[props[prop]]);
if(this.data[props[prop]] != undefined) {
$('#contacts_propertymenu a[data-type="'+props[prop]+'"]').parent().hide();
var property = this.data[props[prop]][0];
var value = property['value'], checksum = property['checksum'];
//console.log('value: ' + property['value']);
//console.log('checksum: ' + property['checksum']);
switch(props[prop]) {
case 'BDAY':
var val = $.datepicker.parseDate('yy-mm-dd', value.substring(0, 10));
//console.log('Date: ' + val);
value = $.datepicker.formatDate('dd-mm-yy', val);
//console.log('Date: ' + value);
$('#contact_identity').find('#bday').val(value);
$('#contact_identity').find('#bday_value').data('checksum', checksum);
$('#contact_identity').find('#bday_label').show();
$('#contact_identity').find('#bday_value').show();
break;
case 'NICKNAME':
//console.log('NICKNAME: ' + value);
$('#contact_identity').find('#nickname').val(value);
$('#contact_identity').find('#nickname_value').data('checksum', checksum);
$('#contact_identity').find('#nickname_label').show();
$('#contact_identity').find('#nickname_value').show();
break;
case 'ORG':
//console.log('ORG: ' + value);
$('#contact_identity').find('#org').val(value);
$('#contact_identity').find('#org_value').data('checksum', checksum);
$('#contact_identity').find('#org_label').show();
$('#contact_identity').find('#org_value').show();
break;
}
}
}
},
populateNameFields:function() {
this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''
var full = '';
var narray = undefined;
//console.log('splitting: ' + this.data.N[0]['value']);
this.fn = this.data.FN[0]['value'];
//console.log('FN: ' + this.fn)
if(this.data.N == undefined) {
narray = [this.fn,'','','','']; // Checking for non-existing 'N' property :-P
full = this.fn;
} else {
narray = this.data.N[0]['value'];
}
this.famname = narray[0];
//console.log('famname: ' + this.famname)
this.givname = narray[1];
this.addname = narray[2];
this.honpre = narray[3];
this.honsuf = narray[4];
if(this.honpre.length > 0) {
this.fullname += this.honpre + ' ';
}
if(this.givname.length > 0) {
this.fullname += ' ' + this.givname;
}
if(this.addname.length > 0) {
this.fullname += ' ' + this.addname;
}
if(this.famname.length > 0) {
this.fullname += ' ' + this.famname;
}
if(this.honsuf.length > 0) {
this.fullname += ', ' + this.honsuf;
}
//console.log('fullname: ' + this.fullname)
$('#n').html(this.fullname);
$('.jecEditableOption').attr('title', 'Custom');
$('.jecEditableOption').text(this.fn);
//$('.jecEditableOption').attr('value', 0);
$('#fn').val(0);
$('#full').text(this.fullname);
$('#short').text(this.givname + ' ' + this.famname);
$('#reverse').text(this.famname + ' ' + this.givname);
$('#reverse_comma').text(this.famname + ', ' + this.givname);
$('#contact_identity').find('*[data-element="N"]').data('checksum', this.data.N[0]['checksum']);
$('#contact_identity').find('*[data-element="FN"]').data('checksum', this.data.FN[0]['checksum']);
},
editNew:function(){ // add a new contact
//Contacts.UI.notImplemented();
//return false;
$.getJSON('ajax/newcontact.php',{},function(jsondata){
if(jsondata.status == 'success'){
id = '';
$('#rightcontent').data('id','');
$('#rightcontent').html(jsondata.data.page);
console.log('Trying to open name edit dialog');
Contacts.UI.Card.editName();
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
alert(jsondata.data.message);
}
});
},
add:function(n, fn, aid){ // add a new contact
//Contacts.UI.notImplemented();
//return false;
console.log('Add contact: ' + n + ', ' + fn + ' ' + aid);
$.post(OC.filePath('contacts', 'ajax', 'addcontact.php'), { n: n, fn: fn, aid: aid },
function(jsondata) {
/*
* Arguments:
* jsondata.status
* jsondata.data.id
*/
if (jsondata.status == 'success'){
$('#rightcontent').data('id',jsondata.data.id);
id = jsondata.data.id;
$('#contact_identity').show();
$('#actionbar').show();
// TODO: Add to contacts list.
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
//alert(jsondata.data.message);
}
});
},
saveProperty:function(obj){
// I couldn't get the selector to filter on 'contacts_property' so I filter by hand here :-/
if(!$(obj).hasClass('contacts_property')) {
//console.log('Filtering out object.' + obj);
return false;
}
console.log('saveProperty. ' + $(obj).val());
if($(obj).hasClass('nonempty') && $(obj).val().trim() == '') {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', 'This property has to be non-empty.'));
return false;
}
//Contacts.UI.loading(obj, false);
//return false;
container = $(obj).parents('.propertycontainer').first(); // get the parent holding the metadata.
Contacts.UI.loading(container, true);
//console.log('saveProperty. Container: ' + container.data('checksum'));
var checksum = container.data('checksum');
var name = container.data('element');
var q = container.find('input,select').serialize();
if(q == '' || q == undefined) {
console.log('Couldn\'t serialize elements.');
Contacts.UI.loading(container, false);
return false;
}
q = q + '&id=' + this.id + '&name=' + name;
if(checksum != undefined && checksum != '') { // save
q = q + '&checksum=' + checksum;
console.log('Saving: ' + q);
$.post('ajax/saveproperty.php',q,function(jsondata){
if(jsondata.status == 'success'){
container.data('checksum', jsondata.data.checksum);
Contacts.UI.loading(container, false);
return true;
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
Contacts.UI.loading(container, false);
return false;
}
},'json');
} else { // add
console.log('Adding: ' + q);
$.post('ajax/addproperty.php',q,function(jsondata){
if(jsondata.status == 'success'){
container.data('checksum', jsondata.data.checksum);
Contacts.UI.loading(container, false);
return true;
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
Contacts.UI.loading(container, false);
return false;
}
},'json');
}
},
addProperty:function(obj){
var type = $(obj).data('type');
console.log('addProperty:' + type);
switch (type) {
case 'PHOTO':
$('#contacts_propertymenu a[data-type="PHOTO"]').parent().hide();
$('#file_upload_form').show();
break;
case 'EMAIL':
//console.log('emails: '+$('#emaillist>li').length);
if($('#emaillist>li').length == 1) {
$('#emails').show();
}
Contacts.UI.Card.addMail();
break;
case 'TEL':
//console.log('phones: '+$('#phonelist>li').length);
if($('#phonelist>li').length == 1) {
$('#phones').show();
}
Contacts.UI.Card.addPhone();
break;
case 'ADR':
//console.log('addresses: '+$('#addressdisplay>dl').length);
if($('#addressdisplay>dl').length == 1) {
$('#addresses').show();
}
Contacts.UI.Card.editAddress('new', true);
break;
case 'NICKNAME':
case 'ORG':
case 'BDAY':
$('dl dt[data-element="'+type+'"],dd[data-element="'+type+'"]').show();
$('#contacts_propertymenu a[data-type="'+type+'"]').parent().hide();
break;
}
},
deleteProperty:function(obj, type){
//console.log('deleteProperty, id: ' + this.id);
Contacts.UI.loading(obj, true);
var checksum = Contacts.UI.checksumFor(obj);
//var checksum = $(obj).parent().data('checksum');
if(checksum != undefined) {
//alert('deleteProperty: ' + $(obj).val() + ' ' + checksum);
$.getJSON('ajax/deleteproperty.php',{'id': this.id, 'checksum': checksum },function(jsondata){
if(jsondata.status == 'success'){
if(type == 'list') {
Contacts.UI.propertyContainerFor(obj).remove();
Contacts.UI.checkListFor(obj);
} else if(type == 'single') {
var proptype = Contacts.UI.propertyTypeFor(obj);
console.log('deleteProperty, hiding: ' + proptype);
$('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide();
$('#contacts_propertymenu a[data-type="'+proptype+'"]').parent().show();
Contacts.UI.loading(obj, false);
} else {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', '\'deleteProperty\' called without type argument. Please report at bugs.owncloud.org'));
Contacts.UI.loading(obj, false);
}
}
else{
Contacts.UI.loading(obj, false);
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
}
});
} else { // Property hasn't been saved so there's nothing to delete.
if(type == 'list') {
Contacts.UI.propertyContainerFor(obj).remove();
Contacts.UI.checkListFor(obj);
} else if(type == 'single') {
var proptype = Contacts.UI.propertyTypeFor(obj);
console.log('deleteProperty, hiding: ' + proptype);
$('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide();
$('#contacts_propertymenu a[data-type="'+proptype+'"]').parent().show();
Contacts.UI.loading(obj, false);
} else {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', '\'deleteProperty\' called without type argument. Please report at bugs.owncloud.org'));
}
}
},
editName:function(){
console.log('editName, id: ' + this.id);
//console.log('editName');
/* Initialize the name edit dialog */
if($('#edit_name_dialog').dialog('isOpen') == true){
$('#edit_name_dialog').dialog('moveToTop');
}else{ // TODO: If id=='' call addcontact.php (or whatever name) instead and reload view with id.
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'editname.php')+'?id='+this.id, function(){
$('#edit_name_dialog' ).dialog({
modal: (this.id == '' && true || false),
closeOnEscape: (this.id == '' && false || true),
title: (this.id == '' && t('contacts', 'Add contact') || t('contacts', 'Edit name')),
height: 'auto', width: 'auto',
buttons: {
'Ok':function() {
Contacts.UI.Card.saveName(this);
$(this).dialog('destroy').remove();
},
'Cancel':function() { $(this).dialog('destroy').remove(); }
},
close : function(event, ui) {
//alert('close');
$(this).dialog('destroy').remove();
//return event;
}/*,
open : function(event, ui) {
// load 'N' property - maybe :-P
}*/
});
});
}
},
saveName:function(dlg){
console.log('saveName, id: ' + this.id);
// TODO: Check if new, get address book id and call Contacts.UI.Card.add()
var n = new Array($(dlg).find('#fam').val(),$(dlg).find('#giv').val(),$(dlg).find('#add').val(),$(dlg).find('#pre').val(),$(dlg).find('#suf').val());
this.famname = n[0];
this.givname = n[1];
this.addname = n[2];
this.honpre = n[3];
this.honsuf = n[4];
//alert('saveName: ' + n);
$('#n').val(n.join(';'));
/*$('#card > input').each(function(){
alert($(this).attr('id') + ' ' + $(this).val());
});*/
if(n[3].length > 0) {
this.fullname = n[3] + ' ';
}
this.fullname += n[1] + ' ' + n[2] + ' ' + n[0];
if(n[4].length > 0) {
this.fullname += ', ' + n[4];
}
$('#short').text(n[1] + ' ' + n[0]);
$('#full').text(this.fullname);
$('#reverse').text(n[0] + ' ' + n[1]);
$('#reverse_comma').text(n[0] + ', ' + n[1]);
//$('#n').html(full);
$('#fn').val(0);
if(this.id == '') {
var aid = $(dlg).find('#aid').val();
Contacts.UI.Card.add(n, $('#short').text(), aid);
} else {
Contacts.UI.Card.saveProperty($('#n'));
}
},
loadAddresses:function(){
$('#addresses').hide();
$('#addressdisplay dl[class*="propertycontainer"]').remove();
for(var adr in this.data.ADR) {
$('#addressdisplay dl').first().clone().insertAfter($('#addressdisplay dl').last()).show();
$('#addressdisplay dl').last().removeClass('template').addClass('propertycontainer');
$('#addressdisplay dl').last().data('checksum', this.data.ADR[adr]['checksum']);
var adrarray = this.data.ADR[adr]['value'];
var adrtxt = '';
if(adrarray[0].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[0].strip_tags() + '</li>';
}
if(adrarray[1].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[1].strip_tags() + '</li>';
}
if(adrarray[2].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[2].strip_tags() + '</li>';
}
if(adrarray[3].length > 0 || adrarray[5].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[5].strip_tags() + ' ' + adrarray[3].strip_tags() + '</li>';
}
if(adrarray[4].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[4].strip_tags() + '</li>';
}
if(adrarray[6].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[6].strip_tags() + '</li>';
}
$('#addressdisplay dl').last().find('.addresslist').html(adrtxt);
//console.log('ADR: ' + adr);
console.log('checksum: ' + this.data.ADR[adr]['checksum']);
//console.log('type: ' + jQuery.type(this.data.ADR[adr]['value']));
var types = new Array();
var ttypes = new Array();
for(var param in this.data.ADR[adr]['parameters']) {
//console.log('param: ' + param + ': ' + this.data.ADR[adr]['parameters'][param]);
if(param.toUpperCase() == 'TYPE') {
//console.log('param type: ' + jQuery.type(this.data.ADR[adr]['parameters'][param]));
types.push(t('contacts', ucwords(this.data.ADR[adr]['parameters'][param].toLowerCase())));
ttypes.push(this.data.ADR[adr]['parameters'][param]);
//for(ptype in this.data.ADR[adr]['parameters'][param]) {
// var pt = this.data.ADR[adr]['parameters'][param][ptype];
// // TODO: Create an array with types, translate, ucwords and join.
//}
}
}
//console.log('# types: ' + types.length);
//console.log('Types:' + types.join('/'));
$('#addressdisplay dl').last().find('.adr_type_label').text(types.join('/'));
$('#addressdisplay dl').last().find('.adr_type').val(ttypes.join(','));
$('#addressdisplay dl').last().find('.adr').val(adrarray.join(';'));
$('#addressdisplay dl').last().data('checksum', this.data.ADR[adr]['checksum']);
}
if($('#addressdisplay dl').length > 1) {
$('#addresses').show();
}
Contacts.UI.loadListHandlers();
return false;
},
editAddress:function(obj, isnew){
console.log('editAddress');
var container = undefined;
var q = q = '?id=' + this.id;
if(obj === 'new') {
isnew = true;
$('#addressdisplay dl').first().clone().insertAfter($('#addressdisplay dl').last()).show();
container = $('#addressdisplay dl').last();
container.removeClass('template').addClass('propertycontainer');
Contacts.UI.loadListHandlers();
} else {
q = q + '&checksum='+Contacts.UI.checksumFor(obj);
}
//console.log('editAddress: checksum ' + checksum);
/* Initialize the address edit dialog */
if($('#edit_address_dialog').dialog('isOpen') == true){
$('#edit_address_dialog').dialog('moveToTop');
}else{
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'editaddress.php')+q, function(){
$('#edit_address_dialog' ).dialog({
/*modal: true,*/
height: 'auto', width: 'auto',
buttons: {
'Ok':function() {
console.log('OK:isnew ' + isnew);
console.log('OK:obj ' + obj);
if(isnew) {
Contacts.UI.Card.saveAddress(this, $('#addressdisplay dl:last-child').find('input').first(), isnew);
} else {
Contacts.UI.Card.saveAddress(this, obj, isnew);
}
$(this).dialog('destroy').remove();
},
'Cancel':function() {
$(this).dialog('destroy').remove();
if(isnew) {
container.remove();
}
}
},
close : function(event, ui) {
//alert('close');
$(this).dialog('destroy').remove();
if(isnew) {
container.remove();
}
}/*,
open : function(event, ui) {
// load 'ADR' property - maybe :-P
}*/
});
});
}
},
saveAddress:function(dlg, obj, isnew){
if(isnew) {
container = $('#addressdisplay dl').last();
obj = $('#addressdisplay dl:last-child').find('input').first();
} else {
checksum = Contacts.UI.checksumFor(obj);
container = Contacts.UI.propertyContainerFor(obj);
}
var adr = new Array($(dlg).find('#adr_pobox').val(),$(dlg).find('#adr_extended').val(),$(dlg).find('#adr_street').val(),$(dlg).find('#adr_city').val(),$(dlg).find('#adr_region').val(),$(dlg).find('#adr_zipcode').val(),$(dlg).find('#adr_country').val());
$(container).find('.adr').val(adr.join(';'));
$(container).find('.adr_type').val($(dlg).find('#adr_type').val());
$(container).find('.adr_type_label').html(t('contacts',ucwords($(dlg).find('#adr_type').val().toLowerCase())));
Contacts.UI.Card.saveProperty($(container).find('input').first());
var adrtxt = '';
if(adr[0].length > 0) {
adrtxt = adrtxt + '<li>' + adr[0] + '</li>';
}
if(adr[1].length > 0) {
adrtxt = adrtxt + '<li>' + adr[1] + '</li>';
}
if(adr[2].length > 0) {
adrtxt = adrtxt + '<li>' + adr[2] + '</li>';
}
if(adr[3].length > 0 || adr[5].length > 0) {
adrtxt = adrtxt + '<li>' + adr[5] + ' ' + adr[3] + '</li>';
}
if(adr[4].length > 0) {
adrtxt = adrtxt + '<li>' + adr[4] + '</li>';
}
if(adr[6].length > 0) {
adrtxt = adrtxt + '<li>' + adr[6] + '</li>';
}
$(container).find('.addresslist').html(adrtxt);
},
uploadPhoto:function(filelist) {
if(!filelist) {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts','No files selected for upload.'));
return;
}
//var file = filelist.item(0);
var file = filelist[0];
var target = $('#file_upload_target');
var form = $('#file_upload_form');
var totalSize=0;
if(file.size > $('#max_upload').val()){
Contacts.UI.messageBox(t('Upload too large'), t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'));
return;
} else {
target.load(function(){
var response=jQuery.parseJSON(target.contents().text());
if(response != undefined && response.status == 'success'){
Contacts.UI.Card.editPhoto(response.data.id, response.data.tmp);
//alert('File: ' + file.tmp + ' ' + file.name + ' ' + file.mime);
}else{
Contacts.UI.messageBox(t('contacts', 'Error'), response.data.message);
}
});
form.submit();
}
},
loadPhoto:function(){
console.log('loadPhoto: ' + this.data.PHOTO);
if(this.data.PHOTO) {
$('#file_upload_form').show();
$('#contacts_propertymenu a[data-type="PHOTO"]').parent().hide();
} else {
$('#file_upload_form').hide();
$('#contacts_propertymenu a[data-type="PHOTO"]').parent().show();
}
$.getJSON('ajax/loadphoto.php',{'id':this.id},function(jsondata){
if(jsondata.status == 'success'){
//alert(jsondata.data.page);
$('#contacts_details_photo_wrapper').html(jsondata.data.page);
}
else{
Contacts.UI.messageBox(jsondata.data.message);
}
});
},
editPhoto:function(id, tmp_path){
//alert('editPhoto: ' + tmp_path);
$.getJSON('ajax/cropphoto.php',{'tmp_path':tmp_path,'id':this.id},function(jsondata){
if(jsondata.status == 'success'){
//alert(jsondata.data.page);
$('#edit_photo_dialog_img').html(jsondata.data.page);
}
else{
Contacts.UI.messageBox(jsondata.data.message);
}
});
if($('#edit_photo_dialog').dialog('isOpen') == true){
$('#edit_photo_dialog').dialog('moveToTop');
} else {
$('#edit_photo_dialog').dialog('open');
}
},
savePhoto:function(){
var target = $('#crop_target');
var form = $('#cropform');
form.submit();
target.load(function(){
var response=jQuery.parseJSON(target.contents().text());
if(response != undefined && response.status == 'success'){
// load cropped photo.
$('#contacts_details_photo_wrapper').html(response.data.page);
}else{
Contacts.UI.messageBox(t('contacts','Error'), response.data.message);
}
});
$('#contacts [data-id="'+this.id+'"]').find('a').css('background','url(thumbnail.php?id='+this.id+'&refresh=1'+Math.random()+') no-repeat');
},
addMail:function() {
//alert('addMail');
$('#emaillist li[class*="template"]:first-child').clone().appendTo($('#emaillist')).show();
$('#emaillist li[class*="template"]:last-child').removeClass('template').addClass('propertycontainer');
$('#emaillist li:last-child').find('input[type="email"]').focus();
Contacts.UI.loadListHandlers();
return false;
},
loadMails:function() {
$('#emails').hide();
$('#emaillist li[class*="propertycontainer"]').remove();
for(var mail in this.data.EMAIL) {
this.addMail();
//$('#emaillist li:first-child').clone().appendTo($('#emaillist')).show();
$('#emaillist li:last-child').data('checksum', this.data.EMAIL[mail]['checksum'])
$('#emaillist li:last-child').find('input[type="email"]').val(this.data.EMAIL[mail]['value']);
//console.log('EMAIL: ' + mail);
//console.log('value: ' + this.data.EMAIL[mail]['value']);
//console.log('checksum: ' + this.data.EMAIL[mail]['checksum']);
for(var param in this.data.EMAIL[mail]['parameters']) {
//console.log('param: ' + param + ': ' + this.data.EMAIL[mail]['parameters'][param]);
if(param.toUpperCase() == 'PREF') {
$('#emaillist li:last-child').find('input[type="checkbox"]').attr('checked', 'checked')
}
}
//console.log('parameters: ' + jQuery.type(this.data.EMAIL[mail]['parameters']));
}
if($('#emaillist li').length > 1) {
$('#emails').show();
}
$('#emaillist li:last-child').find('input[type="text"]').focus();
Contacts.UI.loadListHandlers();
return false;
},
addPhone:function() {
$('#phonelist li[class*="template"]:first-child').clone().appendTo($('#phonelist')); //.show();
$('#phonelist li[class*="template"]:last-child').find('select').addClass('contacts_property');
$('#phonelist li[class*="template"]:last-child').removeClass('template').addClass('propertycontainer');
$('#phonelist li:last-child').find('input[type="text"]').focus();
Contacts.UI.loadListHandlers();
$('#phonelist li:last-child').find('select').multiselect({
noneSelectedText: t('contacts', 'Select type'),
header: false,
selectedList: 4,
classes: 'typelist'
});
$('#phonelist li:last-child').show();
return false;
},
loadPhones:function() {
$('#phones').hide();
$('#phonelist li[class*="propertycontainer"]').remove();
for(var phone in this.data.TEL) {
this.addPhone();
$('#phonelist li:last-child').find('select').multiselect('destroy');
$('#phonelist li:last-child').data('checksum', this.data.TEL[phone]['checksum'])
$('#phonelist li:last-child').find('input[type="text"]').val(this.data.TEL[phone]['value']);
//console.log('TEL: ' + phone);
//console.log('value: ' + this.data.TEL[phone]['value']);
//console.log('checksum: ' + this.data.TEL[phone]['checksum']);
for(var param in this.data.TEL[phone]['parameters']) {
//console.log('param: ' + param + ': ' + this.data.TEL[phone]['parameters'][param]);
if(param.toUpperCase() == 'PREF') {
$('#phonelist li:last-child').find('input[type="checkbox"]').attr('checked', 'checked');
}
else if(param.toUpperCase() == 'TYPE') {
//console.log('param type: ' + jQuery.type(this.data.TEL[phone]['parameters'][param]));
for(ptype in this.data.TEL[phone]['parameters'][param]) {
var pt = this.data.TEL[phone]['parameters'][param][ptype];
$('#phonelist li:last-child').find('select option').each(function(){
//console.log('Test: ' + $(this).val().toUpperCase() + '==' + pt);
if ($(this).val().toUpperCase() == pt) {
//console.log('Selected: ' + pt);
$(this).attr('selected', 'selected');
}
});
}
}
}
$('#phonelist li:last-child').find('select').multiselect({
noneSelectedText: t('contacts', 'Select type'),
header: false,
selectedList: 4,
classes: 'typelist'
});
//console.log('parameters: ' + jQuery.type(this.data.EMAIL[mail]['parameters']));
}
if($('#phonelist li').length > 1) {
$('#phones').show();
}
return false;
},
},
Addressbooks:{
overview:function(){
if($('#chooseaddressbook_dialog').dialog('isOpen') == true){
$('#chooseaddressbook_dialog').dialog('moveToTop');
}else{
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'chooseaddressbook.php'), function(){
$('#chooseaddressbook_dialog').dialog({
width : 600,
close : function(event, ui) {
$(this).dialog('destroy').remove();
}
});
});
}
},
activation:function(checkbox, bookid)
{
$.post(OC.filePath('contacts', 'ajax', 'activation.php'), { bookid: bookid, active: checkbox.checked?1:0 },
function(data) {
/*
* Arguments:
* data.status
* data.bookid
* data.active
*/
if (data.status == 'success'){
checkbox.checked = data.active == 1;
Contacts.UI.Contacts.update();
}
});
},
newAddressbook:function(object){
var tr = $(document.createElement('tr'))
.load(OC.filePath('contacts', 'ajax', 'addbook.php'));
$(object).closest('tr').after(tr).hide();
/* TODO: Shouldn't there be some kinda error checking here? */
},
editAddressbook:function(object, bookid){
var tr = $(document.createElement('tr'))
.load(OC.filePath('contacts', 'ajax', 'editaddressbook.php') + "?bookid="+bookid);
$(object).closest('tr').after(tr).hide();
},
deleteAddressbook:function(bookid){
var check = confirm("Do you really want to delete this address book?");
if(check == false){
return false;
}else{
$.post(OC.filePath('contacts', 'ajax', 'deletebook.php'), { id: bookid},
function(data) {
if (data.status == 'success'){
$('#chooseaddressbook_dialog').dialog('destroy').remove();
Contacts.UI.Contacts.update();
Contacts.UI.Addressbooks.overview();
} else {
Contacts.UI.messageBox(t('contacts', 'Error'), data.message);
//alert('Error: ' + data.message);
}
});
}
},
import:function(){
Contacts.UI.notImplemented();
},
submit:function(button, bookid){
var displayname = $("#displayname_"+bookid).val();
var active = $("#edit_active_"+bookid+":checked").length;
var description = $("#description_"+bookid).val();
var url;
if (bookid == 'new'){
url = OC.filePath('contacts', 'ajax', 'createaddressbook.php');
}else{
url = OC.filePath('contacts', 'ajax', 'updateaddressbook.php');
}
$.post(url, { id: bookid, name: displayname, active: active, description: description },
function(data){
if(data.status == 'success'){
$(button).closest('tr').prev().html(data.page).show().next().remove();
}
});
Contacts.UI.Contacts.update();
},
cancel:function(button, bookid){
$(button).closest('tr').prev().show().next().remove();
}
},
Contacts:{
/**
* Reload the contacts list.
*/
update:function(){
$.getJSON('ajax/contacts.php',{},function(jsondata){
if(jsondata.status == 'success'){
$('#contacts').html(jsondata.data.page);
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'),jsondata.data.message);
//alert(jsondata.data.message);
}
});
setTimeout(Contacts.UI.Contacts.lazyupdate, 500);
},
/**
* Add thumbnails to the contact list as they become visible in the viewport.
*/
lazyupdate:function(){
$('#contacts li').live('inview', function(){
if (!$(this).find('a').attr('style')) {
$(this).find('a').css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
}
});
}
}
}
}
$(document).ready(function(){
Contacts.UI.loadHandlers();
/**
* Show the Addressbook chooser
*/
$('#chooseaddressbook').click(function(){
Contacts.UI.Addressbooks.overview();
return false;
});
/**
* Open blank form to add new contact.
* FIXME: Load the same page but only show name data and popup the name edit dialog.
* On save load the page again with an id and show all fields.
* NOTE: Or: Load the full page and popup name dialog modal. On success set the newly aquired ID, on
* Cancel or failure give appropriate message and show ... something else :-P
*/
$('#contacts_newcontact').click(function(){
Contacts.UI.Card.editNew();
// $.getJSON('ajax/addcontact.php',{},function(jsondata){
// if(jsondata.status == 'success'){
// $('#rightcontent').data('id','');
// $('#rightcontent').html(jsondata.data.page)
// .find('select').chosen();
// }
// else{
// Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
// //alert(jsondata.data.message);
// }
// });
// return false;
});
/**
* Load the details view for a contact.
*/
$('#leftcontent li').live('click',function(){
var id = $(this).data('id');
var oldid = $('#rightcontent').data('id');
if(oldid != 0){
$('#leftcontent li[data-id="'+oldid+'"]').removeClass('active');
}
$.getJSON('ajax/contactdetails.php',{'id':id},function(jsondata){
if(jsondata.status == 'success'){
Contacts.UI.Card.loadContact(jsondata.data);
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
//alert(jsondata.data.message);
}
});
// NOTE: Deprecated.
// $.getJSON('ajax/getdetails.php',{'id':id, 'new':1},function(jsondata){
// if(jsondata.status == 'success'){
// $('#rightcontent').data('id',jsondata.data.id);
// $('#rightcontent').html(jsondata.data.page);
// $('#leftcontent li[data-id="'+jsondata.data.id+'"]').addClass('active');
// //Contacts.UI.loadHandlers();
// }
// else{
// Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
// //alert(jsondata.data.message);
// }
// });
return false;
});
/**
* Delete currently selected contact TODO: and clear page
*/
$('#contacts_deletecard').live('click',function(){
Contacts.UI.Card.delete();
});
/**
* Add and insert a new contact into the list.
*/
$('#contacts_addcardform input[type="submit"]').live('click',function(){
$.post('ajax/addcontact.php',$('#contact_identity').serialize(),function(jsondata){
if(jsondata.status == 'success'){
$('#rightcontent').data('id',jsondata.data.id);
$('#rightcontent').html(jsondata.data.page);
$('#leftcontent .active').removeClass('active');
var item = '<li data-id="'+jsondata.data.id+'" class="active"><a href="index.php?id='+jsondata.data.id+'" style="background: url(thumbnail.php?id='+jsondata.data.id+') no-repeat scroll 0% 0% transparent;">'+jsondata.data.name+'</a></li>';
var added = false;
$('#leftcontent ul li').each(function(){
if ($(this).text().toLowerCase() > jsondata.data.name.toLowerCase()) {
$(this).before(item).fadeIn('fast');
added = true;
return false;
}
});
if(!added) {
$('#leftcontent ul').append(item);
}
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
//alert(jsondata.data.message);
}
}, 'json');
return false;
});
$('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
if (isInView) { //NOTE: I've kept all conditions for future reference ;-)
// element is now visible in the viewport
if (visiblePartY == 'top') {
// top part of element is visible
} else if (visiblePartY == 'bottom') {
// bottom part of element is visible
} else {
// whole part of element is visible
if (!$(this).find('a').attr('style')) {
//alert($(this).data('id') + ' has background: ' + $(this).attr('style'));
$(this).find('a').css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
}/* else {
alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url'));
}*/
}
} else {
// element has gone out of viewport
}
});
$('.button').tipsy();
// Triggers invisible file input
$('#contacts_details_photo').live('click', function() {
$('#file_upload_start').trigger('click');
return false;
});
// NOTE: For some reason the selector doesn't work when I select by '.contacts_property' too...
// I do the filtering in the event handler instead.
$('input[type="text"],input[type="checkbox"],input[type="email"],input[type="tel"],input[type="date"], select').live('change', function(){
Contacts.UI.Card.saveProperty(this);
});
// Name has changed. Update it and reorder.
$('#fn').live('change',function(){
var name = $('#fn').val();
var item = $('#contacts [data-id="'+Contacts.UI.Card.id+'"]').clone();
$('#contacts [data-id="'+Contacts.UI.Card.id+'"]').remove();
$(item).find('a').html(name);
var added = false;
$('#contacts li').each(function(){
if ($(this).text().toLowerCase() > name.toLowerCase()) {
$(this).before(item).fadeIn('fast');
added = true;
return false;
}
});
if(!added) {
$('#leftcontent ul').append(item);
}
});
/**
* Profile picture upload handling
*/
// New profile picture selected
$('#file_upload_start').live('change',function(){
Contacts.UI.Card.uploadPhoto(this.files);
});
$('#contacts_details_photo').bind('dragover',function(event){
console.log('dragover');
$(event.target).css('background-color','red');
event.stopPropagation();
event.preventDefault();
});
$('#contacts_details_photo').bind('dragleave',function(event){
console.log('dragleave');
$(event.target).css('background-color','white');
//event.stopPropagation();
//event.preventDefault();
});
$('#contacts_details_photo').bind('drop',function(event){
event.stopPropagation();
event.preventDefault();
console.log('drop');
$(event.target).css('background-color','white')
$.fileUpload(event.originalEvent.dataTransfer.files);
});
/**
* Upload function for dropped files. Should go in the Contacts class/object.
*/
$.fileUpload = function(files){
var file = files[0];
console.log('size: '+file.size);
if(file.size > $('#max_upload').val()){
Contacts.UI.messageBox(t('contacts','Upload too large'), t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'));
return;
}
if (file.type.indexOf("image") != 0) {
Contacts.UI.messageBox(t('contacts','Wrong file type'), t('contacts','Only image files can be used as profile picture.'));
return;
}
var xhr = new XMLHttpRequest();
if (!xhr.upload) {
Contacts.UI.messageBox(t('contacts', 'Error'), t('contacts', 'Your browser doesn\'t support AJAX upload. Please click on the profile picture to select a photo to upload.'))
}
fileUpload = xhr.upload,
xhr.onreadystatechange = function() {
if (xhr.readyState == 4){
response = $.parseJSON(xhr.responseText);
if(response.status == 'success') {
if(xhr.status == 200) {
Contacts.UI.Card.editPhoto(response.data.id, response.data.tmp);
} else {
Contacts.UI.messageBox(t('contacts', 'Error'), xhr.status + ': ' + xhr.responseText);
}
} else {
//alert(xhr.responseText);
Contacts.UI.messageBox(t('contacts', 'Error'), response.data.message);
}
// stop loading indicator
//$('#contacts_details_photo_progress').hide();
}
};
fileUpload.onprogress = function(e){
if (e.lengthComputable){
var _progress = Math.round((e.loaded * 100) / e.total);
if (_progress != 100){
$('#contacts_details_photo_progress').text(_progress + '%');
$('#contacts_details_photo_progress').val(_progress);
}
}
};
// Start loading indicator.
//$('#contacts_details_photo_progress').show()();
xhr.open("POST", 'ajax/uploadphoto.php?id='+Contacts.UI.Card.id+'&imagefile='+encodeURIComponent(file.name), true);
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name));
//xhr.setRequestHeader("X_FILENAME", file.name);
xhr.setRequestHeader('X-File-Size', file.size);
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
}
$('#contacts_propertymenu a').live('click',function(){
Contacts.UI.Card.addProperty(this);
});
});

1765
js/jquery.Jcrop.js Normal file
View File

@ -0,0 +1,1765 @@
/**
* jquery.Jcrop.js v0.9.9 {{{
*
* jQuery Image Cropping Plugin - released under MIT License
* Author: Kelly Hallman <khallman@gmail.com>
* http://github.com/tapmodo/Jcrop
*
* }}}
* Copyright (c) 2008-2012 Tapmodo Interactive LLC {{{
*
* 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.
*
* }}}
*/
(function ($) {
$.Jcrop = function (obj, opt) {
var options = $.extend({}, $.Jcrop.defaults),
docOffset, lastcurs, ie6mode = false;
// Internal Methods {{{
function px(n) {
return parseInt(n, 10) + 'px';
}
function cssClass(cl) {
return options.baseClass + '-' + cl;
}
function supportsColorFade() {
return $.fx.step.hasOwnProperty('backgroundColor');
}
function getPos(obj) //{{{
{
var pos = $(obj).offset();
return [pos.left, pos.top];
}
//}}}
function mouseAbs(e) //{{{
{
return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];
}
//}}}
function setOptions(opt) //{{{
{
if (typeof(opt) !== 'object') opt = {};
options = $.extend(options, opt);
$.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) {
if (typeof(options[e]) !== 'function') options[e] = function () {};
});
}
//}}}
function startDragMode(mode, pos) //{{{
{
docOffset = getPos($img);
Tracker.setCursor(mode === 'move' ? mode : mode + '-resize');
if (mode === 'move') {
return Tracker.activateHandlers(createMover(pos), doneSelect);
}
var fc = Coords.getFixed();
var opp = oppLockCorner(mode);
var opc = Coords.getCorner(oppLockCorner(opp));
Coords.setPressed(Coords.getCorner(opp));
Coords.setCurrent(opc);
Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect);
}
//}}}
function dragmodeHandler(mode, f) //{{{
{
return function (pos) {
if (!options.aspectRatio) {
switch (mode) {
case 'e':
pos[1] = f.y2;
break;
case 'w':
pos[1] = f.y2;
break;
case 'n':
pos[0] = f.x2;
break;
case 's':
pos[0] = f.x2;
break;
}
} else {
switch (mode) {
case 'e':
pos[1] = f.y + 1;
break;
case 'w':
pos[1] = f.y + 1;
break;
case 'n':
pos[0] = f.x + 1;
break;
case 's':
pos[0] = f.x + 1;
break;
}
}
Coords.setCurrent(pos);
Selection.update();
};
}
//}}}
function createMover(pos) //{{{
{
var lloc = pos;
KeyManager.watchKeys();
return function (pos) {
Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);
lloc = pos;
Selection.update();
};
}
//}}}
function oppLockCorner(ord) //{{{
{
switch (ord) {
case 'n':
return 'sw';
case 's':
return 'nw';
case 'e':
return 'nw';
case 'w':
return 'ne';
case 'ne':
return 'sw';
case 'nw':
return 'se';
case 'se':
return 'nw';
case 'sw':
return 'ne';
}
}
//}}}
function createDragger(ord) //{{{
{
return function (e) {
if (options.disabled) {
return false;
}
if ((ord === 'move') && !options.allowMove) {
return false;
}
// Fix position of crop area when dragged the very first time.
// Necessary when crop image is in a hidden element when page is loaded.
docOffset = getPos($img);
btndown = true;
startDragMode(ord, mouseAbs(e));
e.stopPropagation();
e.preventDefault();
return false;
};
}
//}}}
function presize($obj, w, h) //{{{
{
var nw = $obj.width(),
nh = $obj.height();
if ((nw > w) && w > 0) {
nw = w;
nh = (w / $obj.width()) * $obj.height();
}
if ((nh > h) && h > 0) {
nh = h;
nw = (h / $obj.height()) * $obj.width();
}
xscale = $obj.width() / nw;
yscale = $obj.height() / nh;
$obj.width(nw).height(nh);
}
//}}}
function unscale(c) //{{{
{
return {
x: parseInt(c.x * xscale, 10),
y: parseInt(c.y * yscale, 10),
x2: parseInt(c.x2 * xscale, 10),
y2: parseInt(c.y2 * yscale, 10),
w: parseInt(c.w * xscale, 10),
h: parseInt(c.h * yscale, 10)
};
}
//}}}
function doneSelect(pos) //{{{
{
var c = Coords.getFixed();
if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) {
Selection.enableHandles();
Selection.done();
} else {
Selection.release();
}
Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
}
//}}}
function newSelection(e) //{{{
{
if (options.disabled) {
return false;
}
if (!options.allowSelect) {
return false;
}
btndown = true;
docOffset = getPos($img);
Selection.disableHandles();
Tracker.setCursor('crosshair');
var pos = mouseAbs(e);
Coords.setPressed(pos);
Selection.update();
Tracker.activateHandlers(selectDrag, doneSelect);
KeyManager.watchKeys();
e.stopPropagation();
e.preventDefault();
return false;
}
//}}}
function selectDrag(pos) //{{{
{
Coords.setCurrent(pos);
Selection.update();
}
//}}}
function newTracker() //{{{
{
var trk = $('<div></div>').addClass(cssClass('tracker'));
if ($.browser.msie) {
trk.css({
opacity: 0,
backgroundColor: 'white'
});
}
return trk;
}
//}}}
// }}}
// Initialization {{{
// Sanitize some options {{{
if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) {
ie6mode = true;
}
if (typeof(obj) !== 'object') {
obj = $(obj)[0];
}
if (typeof(opt) !== 'object') {
opt = {};
}
// }}}
setOptions(opt);
// Initialize some jQuery objects {{{
// The values are SET on the image(s) for the interface
// If the original image has any of these set, they will be reset
// However, if you destroy() the Jcrop instance the original image's
// character in the DOM will be as you left it.
var img_css = {
border: 'none',
visibility: 'visible',
margin: 0,
padding: 0,
position: 'absolute',
top: 0,
left: 0
};
var $origimg = $(obj),
img_mode = true;
if (obj.tagName == 'IMG') {
// Fix size of crop image.
// Necessary when crop image is within a hidden element when page is loaded.
if ($origimg[0].width != 0 && $origimg[0].height != 0) {
// Obtain dimensions from contained img element.
$origimg.width($origimg[0].width);
$origimg.height($origimg[0].height);
} else {
// Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
var tempImage = new Image();
tempImage.src = $origimg[0].src;
$origimg.width(tempImage.width);
$origimg.height(tempImage.height);
}
var $img = $origimg.clone().removeAttr('id').css(img_css).show();
$img.width($origimg.width());
$img.height($origimg.height());
$origimg.after($img).hide();
} else {
$img = $origimg.css(img_css).show();
img_mode = false;
if (options.shade === null) { options.shade = true; }
}
presize($img, options.boxWidth, options.boxHeight);
var boundx = $img.width(),
boundy = $img.height(),
$div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
position: 'relative',
backgroundColor: options.bgColor
}).insertAfter($origimg).append($img);
if (options.addClass) {
$div.addClass(options.addClass);
}
var $img2 = $('<div />'),
$img_holder = $('<div />')
.width('100%').height('100%').css({
zIndex: 310,
position: 'absolute',
overflow: 'hidden'
}),
$hdl_holder = $('<div />')
.width('100%').height('100%').css('zIndex', 320),
$sel = $('<div />')
.css({
position: 'absolute',
zIndex: 600
}).dblclick(function(){
var c = Coords.getFixed();
options.onDblClick.call(api,c);
}).insertBefore($img).append($img_holder, $hdl_holder);
if (img_mode) {
$img2 = $('<img />')
.attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),
$img_holder.append($img2);
}
if (ie6mode) {
$sel.css({
overflowY: 'hidden'
});
}
var bound = options.boundary;
var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({
position: 'absolute',
top: px(-bound),
left: px(-bound),
zIndex: 290
}).mousedown(newSelection);
/* }}} */
// Set more variables {{{
var bgcolor = options.bgColor,
bgopacity = options.bgOpacity,
xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true,
btndown, animating, shift_down;
docOffset = getPos($img);
// }}}
// }}}
// Internal Modules {{{
// Touch Module {{{
var Touch = (function () {
// Touch support detection function adapted (under MIT License)
// from code by Jeffrey Sambells - http://github.com/iamamused/
function hasTouchSupport() {
var support = {},
events = ['touchstart', 'touchmove', 'touchend'],
el = document.createElement('div'), i;
try {
for(i=0; i<events.length; i++) {
var eventName = events[i];
eventName = 'on' + eventName;
var isSupported = (eventName in el);
if (!isSupported) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] == 'function';
}
support[events[i]] = isSupported;
}
return support.touchstart && support.touchend && support.touchmove;
}
catch(err) {
return false;
}
}
function detectSupport() {
if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport;
else return hasTouchSupport();
}
return {
createDragger: function (ord) {
return function (e) {
e.pageX = e.originalEvent.changedTouches[0].pageX;
e.pageY = e.originalEvent.changedTouches[0].pageY;
if (options.disabled) {
return false;
}
if ((ord === 'move') && !options.allowMove) {
return false;
}
btndown = true;
startDragMode(ord, mouseAbs(e));
e.stopPropagation();
e.preventDefault();
return false;
};
},
newSelection: function (e) {
e.pageX = e.originalEvent.changedTouches[0].pageX;
e.pageY = e.originalEvent.changedTouches[0].pageY;
return newSelection(e);
},
isSupported: hasTouchSupport,
support: detectSupport()
};
}());
// }}}
// Coords Module {{{
var Coords = (function () {
var x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0,
ox, oy;
function setPressed(pos) //{{{
{
pos = rebound(pos);
x2 = x1 = pos[0];
y2 = y1 = pos[1];
}
//}}}
function setCurrent(pos) //{{{
{
pos = rebound(pos);
ox = pos[0] - x2;
oy = pos[1] - y2;
x2 = pos[0];
y2 = pos[1];
}
//}}}
function getOffset() //{{{
{
return [ox, oy];
}
//}}}
function moveOffset(offset) //{{{
{
var ox = offset[0],
oy = offset[1];
if (0 > x1 + ox) {
ox -= ox + x1;
}
if (0 > y1 + oy) {
oy -= oy + y1;
}
if (boundy < y2 + oy) {
oy += boundy - (y2 + oy);
}
if (boundx < x2 + ox) {
ox += boundx - (x2 + ox);
}
x1 += ox;
x2 += ox;
y1 += oy;
y2 += oy;
}
//}}}
function getCorner(ord) //{{{
{
var c = getFixed();
switch (ord) {
case 'ne':
return [c.x2, c.y];
case 'nw':
return [c.x, c.y];
case 'se':
return [c.x2, c.y2];
case 'sw':
return [c.x, c.y2];
}
}
//}}}
function getFixed() //{{{
{
if (!options.aspectRatio) {
return getRect();
}
// This function could use some optimization I think...
var aspect = options.aspectRatio,
min_x = options.minSize[0] / xscale,
//min_y = options.minSize[1]/yscale,
max_x = options.maxSize[0] / xscale,
max_y = options.maxSize[1] / yscale,
rw = x2 - x1,
rh = y2 - y1,
rwa = Math.abs(rw),
rha = Math.abs(rh),
real_ratio = rwa / rha,
xx, yy, w, h;
if (max_x === 0) {
max_x = boundx * 10;
}
if (max_y === 0) {
max_y = boundy * 10;
}
if (real_ratio < aspect) {
yy = y2;
w = rha * aspect;
xx = rw < 0 ? x1 - w : w + x1;
if (xx < 0) {
xx = 0;
h = Math.abs((xx - x1) / aspect);
yy = rh < 0 ? y1 - h : h + y1;
} else if (xx > boundx) {
xx = boundx;
h = Math.abs((xx - x1) / aspect);
yy = rh < 0 ? y1 - h : h + y1;
}
} else {
xx = x2;
h = rwa / aspect;
yy = rh < 0 ? y1 - h : y1 + h;
if (yy < 0) {
yy = 0;
w = Math.abs((yy - y1) * aspect);
xx = rw < 0 ? x1 - w : w + x1;
} else if (yy > boundy) {
yy = boundy;
w = Math.abs(yy - y1) * aspect;
xx = rw < 0 ? x1 - w : w + x1;
}
}
// Magic %-)
if (xx > x1) { // right side
if (xx - x1 < min_x) {
xx = x1 + min_x;
} else if (xx - x1 > max_x) {
xx = x1 + max_x;
}
if (yy > y1) {
yy = y1 + (xx - x1) / aspect;
} else {
yy = y1 - (xx - x1) / aspect;
}
} else if (xx < x1) { // left side
if (x1 - xx < min_x) {
xx = x1 - min_x;
} else if (x1 - xx > max_x) {
xx = x1 - max_x;
}
if (yy > y1) {
yy = y1 + (x1 - xx) / aspect;
} else {
yy = y1 - (x1 - xx) / aspect;
}
}
if (xx < 0) {
x1 -= xx;
xx = 0;
} else if (xx > boundx) {
x1 -= xx - boundx;
xx = boundx;
}
if (yy < 0) {
y1 -= yy;
yy = 0;
} else if (yy > boundy) {
y1 -= yy - boundy;
yy = boundy;
}
return makeObj(flipCoords(x1, y1, xx, yy));
}
//}}}
function rebound(p) //{{{
{
if (p[0] < 0) {
p[0] = 0;
}
if (p[1] < 0) {
p[1] = 0;
}
if (p[0] > boundx) {
p[0] = boundx;
}
if (p[1] > boundy) {
p[1] = boundy;
}
return [p[0], p[1]];
}
//}}}
function flipCoords(x1, y1, x2, y2) //{{{
{
var xa = x1,
xb = x2,
ya = y1,
yb = y2;
if (x2 < x1) {
xa = x2;
xb = x1;
}
if (y2 < y1) {
ya = y2;
yb = y1;
}
return [Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb)];
}
//}}}
function getRect() //{{{
{
var xsize = x2 - x1,
ysize = y2 - y1,
delta;
if (xlimit && (Math.abs(xsize) > xlimit)) {
x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);
}
if (ylimit && (Math.abs(ysize) > ylimit)) {
y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);
}
if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) {
y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale);
}
if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) {
x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale);
}
if (x1 < 0) {
x2 -= x1;
x1 -= x1;
}
if (y1 < 0) {
y2 -= y1;
y1 -= y1;
}
if (x2 < 0) {
x1 -= x2;
x2 -= x2;
}
if (y2 < 0) {
y1 -= y2;
y2 -= y2;
}
if (x2 > boundx) {
delta = x2 - boundx;
x1 -= delta;
x2 -= delta;
}
if (y2 > boundy) {
delta = y2 - boundy;
y1 -= delta;
y2 -= delta;
}
if (x1 > boundx) {
delta = x1 - boundy;
y2 -= delta;
y1 -= delta;
}
if (y1 > boundy) {
delta = y1 - boundy;
y2 -= delta;
y1 -= delta;
}
return makeObj(flipCoords(x1, y1, x2, y2));
}
//}}}
function makeObj(a) //{{{
{
return {
x: a[0],
y: a[1],
x2: a[2],
y2: a[3],
w: a[2] - a[0],
h: a[3] - a[1]
};
}
//}}}
return {
flipCoords: flipCoords,
setPressed: setPressed,
setCurrent: setCurrent,
getOffset: getOffset,
moveOffset: moveOffset,
getCorner: getCorner,
getFixed: getFixed
};
}());
//}}}
// Shade Module {{{
var Shade = (function() {
var enabled = false,
holder = $('<div />').css({
position: 'absolute',
zIndex: 240,
opacity: 0
}),
shades = {
top: createShade(),
left: createShade().height(boundy),
right: createShade().height(boundy),
bottom: createShade()
};
function resizeShades(w,h) {
shades.left.css({ height: px(h) });
shades.right.css({ height: px(h) });
}
function updateAuto()
{
return updateShade(Coords.getFixed());
}
function updateShade(c)
{
shades.top.css({
left: px(c.x),
width: px(c.w),
height: px(c.y)
});
shades.bottom.css({
top: px(c.y2),
left: px(c.x),
width: px(c.w),
height: px(boundy-c.y2)
});
shades.right.css({
left: px(c.x2),
width: px(boundx-c.x2)
});
shades.left.css({
width: px(c.x)
});
}
function createShade() {
return $('<div />').css({
position: 'absolute',
backgroundColor: options.shadeColor||options.bgColor
}).appendTo(holder);
}
function enableShade() {
if (!enabled) {
enabled = true;
holder.insertBefore($img);
updateAuto();
Selection.setBgOpacity(1,0,1);
$img2.hide();
setBgColor(options.shadeColor||options.bgColor,1);
if (Selection.isAwake())
{
setOpacity(options.bgOpacity,1);
}
else setOpacity(1,1);
}
}
function setBgColor(color,now) {
colorChangeMacro(getShades(),color,now);
}
function disableShade() {
if (enabled) {
holder.remove();
$img2.show();
enabled = false;
if (Selection.isAwake()) {
Selection.setBgOpacity(options.bgOpacity,1,1);
} else {
Selection.setBgOpacity(1,1,1);
Selection.disableHandles();
}
colorChangeMacro($div,0,1);
}
}
function setOpacity(opacity,now) {
if (enabled) {
if (options.bgFade && !now) {
holder.animate({
opacity: 1-opacity
},{
queue: false,
duration: options.fadeTime
});
}
else holder.css({opacity:1-opacity});
}
}
function refreshAll() {
options.shade ? enableShade() : disableShade();
if (Selection.isAwake()) setOpacity(options.bgOpacity);
}
function getShades() {
return holder.children();
}
return {
update: updateAuto,
updateRaw: updateShade,
getShades: getShades,
setBgColor: setBgColor,
enable: enableShade,
disable: disableShade,
resize: resizeShades,
refresh: refreshAll,
opacity: setOpacity
};
}());
// }}}
// Selection Module {{{
var Selection = (function () {
var awake, hdep = 370;
var borders = {};
var handle = {};
var seehandles = false;
var hhs = options.handleOffset;
// Private Methods
function insertBorder(type) //{{{
{
var jq = $('<div />').css({
position: 'absolute',
opacity: options.borderOpacity
}).addClass(cssClass(type));
$img_holder.append(jq);
return jq;
}
//}}}
function dragDiv(ord, zi) //{{{
{
var jq = $('<div />').mousedown(createDragger(ord)).css({
cursor: ord + '-resize',
position: 'absolute',
zIndex: zi
}).addClass('ord-'+ord);
if (Touch.support) {
jq.bind('touchstart.jcrop', Touch.createDragger(ord));
}
$hdl_holder.append(jq);
return jq;
}
//}}}
function insertHandle(ord) //{{{
{
var hs = options.handleSize;
return dragDiv(ord, hdep++).css({
top: px(-hhs + 1),
left: px(-hhs + 1),
opacity: options.handleOpacity
}).width(hs).height(hs).addClass(cssClass('handle'));
}
//}}}
function insertDragbar(ord) //{{{
{
var s = options.handleSize,
h = s,
w = s,
t = hhs,
l = hhs;
switch (ord) {
case 'n':
case 's':
w = '100%';
break;
case 'e':
case 'w':
h = '100%';
break;
}
return dragDiv(ord, hdep++).width(w).height(h).css({
top: px(-t + 1),
left: px(-l + 1)
});
}
//}}}
function createHandles(li) //{{{
{
var i;
for (i = 0; i < li.length; i++) {
handle[li[i]] = insertHandle(li[i]);
}
}
//}}}
function moveHandles(c) //{{{
{
var midvert = Math.round((c.h / 2) - hhs),
midhoriz = Math.round((c.w / 2) - hhs),
north = -hhs + 1,
west = -hhs + 1,
east = c.w - hhs,
south = c.h - hhs,
x, y;
if (handle.e) {
handle.e.css({
top: px(midvert),
left: px(east)
});
handle.w.css({
top: px(midvert)
});
handle.s.css({
top: px(south),
left: px(midhoriz)
});
handle.n.css({
left: px(midhoriz)
});
}
if (handle.ne) {
handle.ne.css({
left: px(east)
});
handle.se.css({
top: px(south),
left: px(east)
});
handle.sw.css({
top: px(south)
});
}
if (handle.b) {
handle.b.css({
top: px(south)
});
handle.r.css({
left: px(east)
});
}
}
//}}}
function moveto(x, y) //{{{
{
if (!options.shade) {
$img2.css({
top: px(-y),
left: px(-x)
});
}
$sel.css({
top: px(y),
left: px(x)
});
}
//}}}
function resize(w, h) //{{{
{
$sel.width(w).height(h);
}
//}}}
function refresh() //{{{
{
var c = Coords.getFixed();
Coords.setPressed([c.x, c.y]);
Coords.setCurrent([c.x2, c.y2]);
updateVisible();
}
//}}}
// Internal Methods
function updateVisible(select) //{{{
{
if (awake) {
return update(select);
}
}
//}}}
function update(select) //{{{
{
var c = Coords.getFixed();
resize(c.w, c.h);
moveto(c.x, c.y);
if (options.shade) Shade.updateRaw(c);
if (seehandles) {
moveHandles(c);
}
if (!awake) {
show();
}
if (select) {
options.onSelect.call(api, unscale(c));
} else {
options.onChange.call(api, unscale(c));
}
}
//}}}
function setBgOpacity(opacity,force,now)
{
if (!awake && !force) return;
if (options.bgFade && !now) {
$img.animate({
opacity: opacity
},{
queue: false,
duration: options.fadeTime
});
} else {
$img.css('opacity', opacity);
}
}
function show() //{{{
{
$sel.show();
if (options.shade) Shade.opacity(bgopacity);
else setBgOpacity(bgopacity,true);
awake = true;
}
//}}}
function release() //{{{
{
disableHandles();
$sel.hide();
if (options.shade) Shade.opacity(1);
else setBgOpacity(1);
awake = false;
options.onRelease.call(api);
}
//}}}
function showHandles() //{{{
{
if (seehandles) {
moveHandles(Coords.getFixed());
$hdl_holder.show();
}
}
//}}}
function enableHandles() //{{{
{
seehandles = true;
if (options.allowResize) {
moveHandles(Coords.getFixed());
$hdl_holder.show();
return true;
}
}
//}}}
function disableHandles() //{{{
{
seehandles = false;
$hdl_holder.hide();
}
//}}}
function animMode(v) //{{{
{
if (animating === v) {
disableHandles();
} else {
enableHandles();
}
}
//}}}
function done() //{{{
{
animMode(false);
refresh();
}
//}}}
/* Insert draggable elements {{{*/
// Insert border divs for outline
if (options.drawBorders) {
borders = {
top: insertBorder('hline'),
bottom: insertBorder('hline bottom'),
left: insertBorder('vline'),
right: insertBorder('vline right')
};
}
// Insert handles on edges
if (options.dragEdges) {
handle.t = insertDragbar('n');
handle.b = insertDragbar('s');
handle.r = insertDragbar('e');
handle.l = insertDragbar('w');
}
// Insert side and corner handles
if (options.sideHandles) {
createHandles(['n', 's', 'e', 'w']);
}
if (options.cornerHandles) {
createHandles(['sw', 'nw', 'ne', 'se']);
}
//}}}
// This is a hack for iOS5 to support drag/move touch functionality
$(document).bind('touchstart.jcrop-ios',function(e) {
if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation();
});
var $track = newTracker().mousedown(createDragger('move')).css({
cursor: 'move',
position: 'absolute',
zIndex: 360
});
if (Touch.support) {
$track.bind('touchstart.jcrop', Touch.createDragger('move'));
}
$img_holder.append($track);
disableHandles();
return {
updateVisible: updateVisible,
update: update,
release: release,
refresh: refresh,
isAwake: function () {
return awake;
},
setCursor: function (cursor) {
$track.css('cursor', cursor);
},
enableHandles: enableHandles,
enableOnly: function () {
seehandles = true;
},
showHandles: showHandles,
disableHandles: disableHandles,
animMode: animMode,
setBgOpacity: setBgOpacity,
done: done
};
}());
//}}}
// Tracker Module {{{
var Tracker = (function () {
var onMove = function () {},
onDone = function () {},
trackDoc = options.trackDocument;
function toFront() //{{{
{
$trk.css({
zIndex: 450
});
if (Touch.support) {
$(document)
.bind('touchmove.jcrop', trackTouchMove)
.bind('touchend.jcrop', trackTouchEnd);
}
if (trackDoc) {
$(document)
.bind('mousemove.jcrop',trackMove)
.bind('mouseup.jcrop',trackUp);
}
}
//}}}
function toBack() //{{{
{
$trk.css({
zIndex: 290
});
$(document).unbind('.jcrop');
}
//}}}
function trackMove(e) //{{{
{
onMove(mouseAbs(e));
return false;
}
//}}}
function trackUp(e) //{{{
{
e.preventDefault();
e.stopPropagation();
if (btndown) {
btndown = false;
onDone(mouseAbs(e));
if (Selection.isAwake()) {
options.onSelect.call(api, unscale(Coords.getFixed()));
}
toBack();
onMove = function () {};
onDone = function () {};
}
return false;
}
//}}}
function activateHandlers(move, done) //{{{
{
btndown = true;
onMove = move;
onDone = done;
toFront();
return false;
}
//}}}
function trackTouchMove(e) //{{{
{
e.pageX = e.originalEvent.changedTouches[0].pageX;
e.pageY = e.originalEvent.changedTouches[0].pageY;
return trackMove(e);
}
//}}}
function trackTouchEnd(e) //{{{
{
e.pageX = e.originalEvent.changedTouches[0].pageX;
e.pageY = e.originalEvent.changedTouches[0].pageY;
return trackUp(e);
}
//}}}
function setCursor(t) //{{{
{
$trk.css('cursor', t);
}
//}}}
if (!trackDoc) {
$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
}
$img.before($trk);
return {
activateHandlers: activateHandlers,
setCursor: setCursor
};
}());
//}}}
// KeyManager Module {{{
var KeyManager = (function () {
var $keymgr = $('<input type="radio" />').css({
position: 'fixed',
left: '-120px',
width: '12px'
}),
$keywrap = $('<div />').css({
position: 'absolute',
overflow: 'hidden'
}).append($keymgr);
function watchKeys() //{{{
{
if (options.keySupport) {
$keymgr.show();
$keymgr.focus();
}
}
//}}}
function onBlur(e) //{{{
{
$keymgr.hide();
}
//}}}
function doNudge(e, x, y) //{{{
{
if (options.allowMove) {
Coords.moveOffset([x, y]);
Selection.updateVisible(true);
}
e.preventDefault();
e.stopPropagation();
}
//}}}
function parseKey(e) //{{{
{
if (e.ctrlKey || e.metaKey) {
return true;
}
shift_down = e.shiftKey ? true : false;
var nudge = shift_down ? 10 : 1;
switch (e.keyCode) {
case 37:
doNudge(e, -nudge, 0);
break;
case 39:
doNudge(e, nudge, 0);
break;
case 38:
doNudge(e, 0, -nudge);
break;
case 40:
doNudge(e, 0, nudge);
break;
case 27:
if (options.allowSelect) Selection.release();
break;
case 9:
return true;
}
return false;
}
//}}}
if (options.keySupport) {
$keymgr.keydown(parseKey).blur(onBlur);
if (ie6mode || !options.fixedSupport) {
$keymgr.css({
position: 'absolute',
left: '-20px'
});
$keywrap.append($keymgr).insertBefore($img);
} else {
$keymgr.insertBefore($img);
}
}
return {
watchKeys: watchKeys
};
}());
//}}}
// }}}
// API methods {{{
function setClass(cname) //{{{
{
$div.removeClass().addClass(cssClass('holder')).addClass(cname);
}
//}}}
function animateTo(a, callback) //{{{
{
var x1 = parseInt(a[0], 10) / xscale,
y1 = parseInt(a[1], 10) / yscale,
x2 = parseInt(a[2], 10) / xscale,
y2 = parseInt(a[3], 10) / yscale;
if (animating) {
return;
}
var animto = Coords.flipCoords(x1, y1, x2, y2),
c = Coords.getFixed(),
initcr = [c.x, c.y, c.x2, c.y2],
animat = initcr,
interv = options.animationDelay,
ix1 = animto[0] - initcr[0],
iy1 = animto[1] - initcr[1],
ix2 = animto[2] - initcr[2],
iy2 = animto[3] - initcr[3],
pcent = 0,
velocity = options.swingSpeed;
x = animat[0];
y = animat[1];
x2 = animat[2];
y2 = animat[3];
Selection.animMode(true);
var anim_timer;
function queueAnimator() {
window.setTimeout(animator, interv);
}
var animator = (function () {
return function () {
pcent += (100 - pcent) / velocity;
animat[0] = x + ((pcent / 100) * ix1);
animat[1] = y + ((pcent / 100) * iy1);
animat[2] = x2 + ((pcent / 100) * ix2);
animat[3] = y2 + ((pcent / 100) * iy2);
if (pcent >= 99.8) {
pcent = 100;
}
if (pcent < 100) {
setSelectRaw(animat);
queueAnimator();
} else {
Selection.done();
if (typeof(callback) === 'function') {
callback.call(api);
}
}
};
}());
queueAnimator();
}
//}}}
function setSelect(rect) //{{{
{
setSelectRaw([parseInt(rect[0], 10) / xscale, parseInt(rect[1], 10) / yscale, parseInt(rect[2], 10) / xscale, parseInt(rect[3], 10) / yscale]);
options.onSelect.call(api, unscale(Coords.getFixed()));
Selection.enableHandles();
}
//}}}
function setSelectRaw(l) //{{{
{
Coords.setPressed([l[0], l[1]]);
Coords.setCurrent([l[2], l[3]]);
Selection.update();
}
//}}}
function tellSelect() //{{{
{
return unscale(Coords.getFixed());
}
//}}}
function tellScaled() //{{{
{
return Coords.getFixed();
}
//}}}
function setOptionsNew(opt) //{{{
{
setOptions(opt);
interfaceUpdate();
}
//}}}
function disableCrop() //{{{
{
options.disabled = true;
Selection.disableHandles();
Selection.setCursor('default');
Tracker.setCursor('default');
}
//}}}
function enableCrop() //{{{
{
options.disabled = false;
interfaceUpdate();
}
//}}}
function cancelCrop() //{{{
{
Selection.done();
Tracker.activateHandlers(null, null);
}
//}}}
function destroy() //{{{
{
$div.remove();
$origimg.show();
$(obj).removeData('Jcrop');
}
//}}}
function setImage(src, callback) //{{{
{
Selection.release();
disableCrop();
var img = new Image();
img.onload = function () {
var iw = img.width;
var ih = img.height;
var bw = options.boxWidth;
var bh = options.boxHeight;
$img.width(iw).height(ih);
$img.attr('src', src);
$img2.attr('src', src);
presize($img, bw, bh);
boundx = $img.width();
boundy = $img.height();
$img2.width(boundx).height(boundy);
$trk.width(boundx + (bound * 2)).height(boundy + (bound * 2));
$div.width(boundx).height(boundy);
Shade.resize(boundx,boundy);
enableCrop();
if (typeof(callback) === 'function') {
callback.call(api);
}
};
img.src = src;
}
//}}}
function colorChangeMacro($obj,color,now) {
var mycolor = color || options.bgColor;
if (options.bgFade && supportsColorFade() && options.fadeTime && !now) {
$obj.animate({
backgroundColor: mycolor
}, {
queue: false,
duration: options.fadeTime
});
} else {
$obj.css('backgroundColor', mycolor);
}
}
function interfaceUpdate(alt) //{{{
// This method tweaks the interface based on options object.
// Called when options are changed and at end of initialization.
{
if (options.allowResize) {
if (alt) {
Selection.enableOnly();
} else {
Selection.enableHandles();
}
} else {
Selection.disableHandles();
}
Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
Selection.setCursor(options.allowMove ? 'move' : 'default');
if (options.hasOwnProperty('trueSize')) {
xscale = options.trueSize[0] / boundx;
yscale = options.trueSize[1] / boundy;
}
if (options.hasOwnProperty('setSelect')) {
setSelect(options.setSelect);
Selection.done();
delete(options.setSelect);
}
Shade.refresh();
if (options.bgColor != bgcolor) {
colorChangeMacro(
options.shade? Shade.getShades(): $div,
options.shade?
(options.shadeColor || options.bgColor):
options.bgColor
);
bgcolor = options.bgColor;
}
if (bgopacity != options.bgOpacity) {
bgopacity = options.bgOpacity;
if (options.shade) Shade.refresh();
else Selection.setBgOpacity(bgopacity);
}
xlimit = options.maxSize[0] || 0;
ylimit = options.maxSize[1] || 0;
xmin = options.minSize[0] || 0;
ymin = options.minSize[1] || 0;
if (options.hasOwnProperty('outerImage')) {
$img.attr('src', options.outerImage);
delete(options.outerImage);
}
Selection.refresh();
}
//}}}
//}}}
if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection);
$hdl_holder.hide();
interfaceUpdate(true);
var api = {
setImage: setImage,
animateTo: animateTo,
setSelect: setSelect,
setOptions: setOptionsNew,
tellSelect: tellSelect,
tellScaled: tellScaled,
setClass: setClass,
disable: disableCrop,
enable: enableCrop,
cancel: cancelCrop,
release: Selection.release,
destroy: destroy,
focus: KeyManager.watchKeys,
getBounds: function () {
return [boundx * xscale, boundy * yscale];
},
getWidgetSize: function () {
return [boundx, boundy];
},
getScaleFactor: function () {
return [xscale, yscale];
},
ui: {
holder: $div,
selection: $sel
}
};
if ($.browser.msie) {
$div.bind('selectstart', function () {
return false;
});
}
$origimg.data('Jcrop', api);
return api;
};
$.fn.Jcrop = function (options, callback) //{{{
{
var api;
// Iterate over each object, attach Jcrop
this.each(function () {
// If we've already attached to this object
if ($(this).data('Jcrop')) {
// The API can be requested this way (undocumented)
if (options === 'api') return $(this).data('Jcrop');
// Otherwise, we just reset the options...
else $(this).data('Jcrop').setOptions(options);
}
// If we haven't been attached, preload and attach
else {
if (this.tagName == 'IMG')
$.Jcrop.Loader(this,function(){
$(this).css({display:'block',visibility:'hidden'});
api = $.Jcrop(this, options);
if ($.isFunction(callback)) callback.call(api);
});
else {
$(this).css({display:'block',visibility:'hidden'});
api = $.Jcrop(this, options);
if ($.isFunction(callback)) callback.call(api);
}
}
});
// Return "this" so the object is chainable (jQuery-style)
return this;
};
//}}}
// $.Jcrop.Loader - basic image loader {{{
$.Jcrop.Loader = function(imgobj,success,error){
var $img = $(imgobj), img = $img[0];
function completeCheck(){
if (img.complete) {
$img.unbind('.jcloader');
if ($.isFunction(success)) success.call(img);
}
else window.setTimeout(completeCheck,50);
}
$img
.bind('load.jcloader',completeCheck)
.bind('error.jcloader',function(e){
$img.unbind('.jcloader');
if ($.isFunction(error)) error.call(img);
});
if (img.complete && $.isFunction(success)){
$img.unbind('.jcloader');
success.call(img);
}
};
//}}}
// Global Defaults {{{
$.Jcrop.defaults = {
// Basic Settings
allowSelect: true,
allowMove: true,
allowResize: true,
trackDocument: true,
// Styling Options
baseClass: 'jcrop',
addClass: null,
bgColor: 'black',
bgOpacity: 0.6,
bgFade: false,
borderOpacity: 0.4,
handleOpacity: 0.5,
handleSize: 7,
handleOffset: 5,
aspectRatio: 0,
keySupport: true,
cornerHandles: true,
sideHandles: true,
drawBorders: true,
dragEdges: true,
fixedSupport: true,
touchSupport: null,
shade: null,
boxWidth: 0,
boxHeight: 0,
boundary: 2,
fadeTime: 400,
animationDelay: 20,
swingSpeed: 3,
minSelect: [0, 0],
maxSize: [0, 0],
minSize: [0, 0],
// Callbacks / Event Handlers
onChange: function () {},
onSelect: function () {},
onDblClick: function () {},
onRelease: function () {}
};
// }}}
}(jQuery));

255
js/jquery.Jcrop.min.js vendored Normal file
View File

@ -0,0 +1,255 @@
/**
* jquery.Jcrop.min.js v0.9.9 {{{ (build:20120102)
* jQuery Image Cropping Plugin - released under MIT License
* Copyright (c) 2008-2012 Tapmodo Interactive LLC
* https://github.com/tapmodo/Jcrop
*/
(function($){$.Jcrop=function(obj,opt){var options=$.extend({},$.Jcrop.defaults),docOffset,lastcurs,ie6mode=false;function px(n){return parseInt(n,10)+'px';}
function cssClass(cl){return options.baseClass+'-'+cl;}
function supportsColorFade(){return $.fx.step.hasOwnProperty('backgroundColor');}
function getPos(obj)
{var pos=$(obj).offset();return[pos.left,pos.top];}
function mouseAbs(e)
{return[(e.pageX-docOffset[0]),(e.pageY-docOffset[1])];}
function setOptions(opt)
{if(typeof(opt)!=='object')opt={};options=$.extend(options,opt);$.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e){if(typeof(options[e])!=='function')options[e]=function(){};});}
function startDragMode(mode,pos)
{docOffset=getPos($img);Tracker.setCursor(mode==='move'?mode:mode+'-resize');if(mode==='move'){return Tracker.activateHandlers(createMover(pos),doneSelect);}
var fc=Coords.getFixed();var opp=oppLockCorner(mode);var opc=Coords.getCorner(oppLockCorner(opp));Coords.setPressed(Coords.getCorner(opp));Coords.setCurrent(opc);Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect);}
function dragmodeHandler(mode,f)
{return function(pos){if(!options.aspectRatio){switch(mode){case'e':pos[1]=f.y2;break;case'w':pos[1]=f.y2;break;case'n':pos[0]=f.x2;break;case's':pos[0]=f.x2;break;}}else{switch(mode){case'e':pos[1]=f.y+1;break;case'w':pos[1]=f.y+1;break;case'n':pos[0]=f.x+1;break;case's':pos[0]=f.x+1;break;}}
Coords.setCurrent(pos);Selection.update();};}
function createMover(pos)
{var lloc=pos;KeyManager.watchKeys();return function(pos){Coords.moveOffset([pos[0]-lloc[0],pos[1]-lloc[1]]);lloc=pos;Selection.update();};}
function oppLockCorner(ord)
{switch(ord){case'n':return'sw';case's':return'nw';case'e':return'nw';case'w':return'ne';case'ne':return'sw';case'nw':return'se';case'se':return'nw';case'sw':return'ne';}}
function createDragger(ord)
{return function(e){if(options.disabled){return false;}
if((ord==='move')&&!options.allowMove){return false;}
docOffset=getPos($img);btndown=true;startDragMode(ord,mouseAbs(e));e.stopPropagation();e.preventDefault();return false;};}
function presize($obj,w,h)
{var nw=$obj.width(),nh=$obj.height();if((nw>w)&&w>0){nw=w;nh=(w/$obj.width())*$obj.height();}
if((nh>h)&&h>0){nh=h;nw=(h/$obj.height())*$obj.width();}
xscale=$obj.width()/nw;yscale=$obj.height()/nh;$obj.width(nw).height(nh);}
function unscale(c)
{return{x:parseInt(c.x*xscale,10),y:parseInt(c.y*yscale,10),x2:parseInt(c.x2*xscale,10),y2:parseInt(c.y2*yscale,10),w:parseInt(c.w*xscale,10),h:parseInt(c.h*yscale,10)};}
function doneSelect(pos)
{var c=Coords.getFixed();if((c.w>options.minSelect[0])&&(c.h>options.minSelect[1])){Selection.enableHandles();Selection.done();}else{Selection.release();}
Tracker.setCursor(options.allowSelect?'crosshair':'default');}
function newSelection(e)
{if(options.disabled){return false;}
if(!options.allowSelect){return false;}
btndown=true;docOffset=getPos($img);Selection.disableHandles();Tracker.setCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Selection.update();Tracker.activateHandlers(selectDrag,doneSelect);KeyManager.watchKeys();e.stopPropagation();e.preventDefault();return false;}
function selectDrag(pos)
{Coords.setCurrent(pos);Selection.update();}
function newTracker()
{var trk=$('<div></div>').addClass(cssClass('tracker'));if($.browser.msie){trk.css({opacity:0,backgroundColor:'white'});}
return trk;}
if($.browser.msie&&($.browser.version.split('.')[0]==='6')){ie6mode=true;}
if(typeof(obj)!=='object'){obj=$(obj)[0];}
if(typeof(opt)!=='object'){opt={};}
setOptions(opt);var img_css={border:'none',visibility:'visible',margin:0,padding:0,position:'absolute',top:0,left:0};var $origimg=$(obj),img_mode=true;if(obj.tagName=='IMG'){if($origimg[0].width!=0&&$origimg[0].height!=0){$origimg.width($origimg[0].width);$origimg.height($origimg[0].height);}else{var tempImage=new Image();tempImage.src=$origimg[0].src;$origimg.width(tempImage.width);$origimg.height(tempImage.height);}
var $img=$origimg.clone().removeAttr('id').css(img_css).show();$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();}else{$img=$origimg.css(img_css).show();img_mode=false;if(options.shade===null){options.shade=true;}}
presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);if(options.addClass){$div.addClass(options.addClass);}
var $img2=$('<div />'),$img_holder=$('<div />').width('100%').height('100%').css({zIndex:310,position:'absolute',overflow:'hidden'}),$hdl_holder=$('<div />').width('100%').height('100%').css('zIndex',320),$sel=$('<div />').css({position:'absolute',zIndex:600}).dblclick(function(){var c=Coords.getFixed();options.onDblClick.call(api,c);}).insertBefore($img).append($img_holder,$hdl_holder);if(img_mode){$img2=$('<img />').attr('src',$img.attr('src')).css(img_css).width(boundx).height(boundy),$img_holder.append($img2);}
if(ie6mode){$sel.css({overflowY:'hidden'});}
var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var bgcolor=options.bgColor,bgopacity=options.bgOpacity,xlimit,ylimit,xmin,ymin,xscale,yscale,enabled=true,btndown,animating,shift_down;docOffset=getPos($img);var Touch=(function(){function hasTouchSupport(){var support={},events=['touchstart','touchmove','touchend'],el=document.createElement('div'),i;try{for(i=0;i<events.length;i++){var eventName=events[i];eventName='on'+eventName;var isSupported=(eventName in el);if(!isSupported){el.setAttribute(eventName,'return;');isSupported=typeof el[eventName]=='function';}
support[events[i]]=isSupported;}
return support.touchstart&&support.touchend&&support.touchmove;}
catch(err){return false;}}
function detectSupport(){if((options.touchSupport===true)||(options.touchSupport===false))return options.touchSupport;else return hasTouchSupport();}
return{createDragger:function(ord){return function(e){e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;if(options.disabled){return false;}
if((ord==='move')&&!options.allowMove){return false;}
btndown=true;startDragMode(ord,mouseAbs(e));e.stopPropagation();e.preventDefault();return false;};},newSelection:function(e){e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return newSelection(e);},isSupported:hasTouchSupport,support:detectSupport()};}());var Coords=(function(){var x1=0,y1=0,x2=0,y2=0,ox,oy;function setPressed(pos)
{pos=rebound(pos);x2=x1=pos[0];y2=y1=pos[1];}
function setCurrent(pos)
{pos=rebound(pos);ox=pos[0]-x2;oy=pos[1]-y2;x2=pos[0];y2=pos[1];}
function getOffset()
{return[ox,oy];}
function moveOffset(offset)
{var ox=offset[0],oy=offset[1];if(0>x1+ox){ox-=ox+x1;}
if(0>y1+oy){oy-=oy+y1;}
if(boundy<y2+oy){oy+=boundy-(y2+oy);}
if(boundx<x2+ox){ox+=boundx-(x2+ox);}
x1+=ox;x2+=ox;y1+=oy;y2+=oy;}
function getCorner(ord)
{var c=getFixed();switch(ord){case'ne':return[c.x2,c.y];case'nw':return[c.x,c.y];case'se':return[c.x2,c.y2];case'sw':return[c.x,c.y2];}}
function getFixed()
{if(!options.aspectRatio){return getRect();}
var aspect=options.aspectRatio,min_x=options.minSize[0]/xscale,max_x=options.maxSize[0]/xscale,max_y=options.maxSize[1]/yscale,rw=x2-x1,rh=y2-y1,rwa=Math.abs(rw),rha=Math.abs(rh),real_ratio=rwa/rha,xx,yy,w,h;if(max_x===0){max_x=boundx*10;}
if(max_y===0){max_y=boundy*10;}
if(real_ratio<aspect){yy=y2;w=rha*aspect;xx=rw<0?x1-w:w+x1;if(xx<0){xx=0;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}else if(xx>boundx){xx=boundx;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}}else{xx=x2;h=rwa/aspect;yy=rh<0?y1-h:y1+h;if(yy<0){yy=0;w=Math.abs((yy-y1)*aspect);xx=rw<0?x1-w:w+x1;}else if(yy>boundy){yy=boundy;w=Math.abs(yy-y1)*aspect;xx=rw<0?x1-w:w+x1;}}
if(xx>x1){if(xx-x1<min_x){xx=x1+min_x;}else if(xx-x1>max_x){xx=x1+max_x;}
if(yy>y1){yy=y1+(xx-x1)/aspect;}else{yy=y1-(xx-x1)/aspect;}}else if(xx<x1){if(x1-xx<min_x){xx=x1-min_x;}else if(x1-xx>max_x){xx=x1-max_x;}
if(yy>y1){yy=y1+(x1-xx)/aspect;}else{yy=y1-(x1-xx)/aspect;}}
if(xx<0){x1-=xx;xx=0;}else if(xx>boundx){x1-=xx-boundx;xx=boundx;}
if(yy<0){y1-=yy;yy=0;}else if(yy>boundy){y1-=yy-boundy;yy=boundy;}
return makeObj(flipCoords(x1,y1,xx,yy));}
function rebound(p)
{if(p[0]<0){p[0]=0;}
if(p[1]<0){p[1]=0;}
if(p[0]>boundx){p[0]=boundx;}
if(p[1]>boundy){p[1]=boundy;}
return[p[0],p[1]];}
function flipCoords(x1,y1,x2,y2)
{var xa=x1,xb=x2,ya=y1,yb=y2;if(x2<x1){xa=x2;xb=x1;}
if(y2<y1){ya=y2;yb=y1;}
return[Math.round(xa),Math.round(ya),Math.round(xb),Math.round(yb)];}
function getRect()
{var xsize=x2-x1,ysize=y2-y1,delta;if(xlimit&&(Math.abs(xsize)>xlimit)){x2=(xsize>0)?(x1+xlimit):(x1-xlimit);}
if(ylimit&&(Math.abs(ysize)>ylimit)){y2=(ysize>0)?(y1+ylimit):(y1-ylimit);}
if(ymin/yscale&&(Math.abs(ysize)<ymin/yscale)){y2=(ysize>0)?(y1+ymin/yscale):(y1-ymin/yscale);}
if(xmin/xscale&&(Math.abs(xsize)<xmin/xscale)){x2=(xsize>0)?(x1+xmin/xscale):(x1-xmin/xscale);}
if(x1<0){x2-=x1;x1-=x1;}
if(y1<0){y2-=y1;y1-=y1;}
if(x2<0){x1-=x2;x2-=x2;}
if(y2<0){y1-=y2;y2-=y2;}
if(x2>boundx){delta=x2-boundx;x1-=delta;x2-=delta;}
if(y2>boundy){delta=y2-boundy;y1-=delta;y2-=delta;}
if(x1>boundx){delta=x1-boundy;y2-=delta;y1-=delta;}
if(y1>boundy){delta=y1-boundy;y2-=delta;y1-=delta;}
return makeObj(flipCoords(x1,y1,x2,y2));}
function makeObj(a)
{return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};}
return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}());var Shade=(function(){var enabled=false,holder=$('<div />').css({position:'absolute',zIndex:240,opacity:0}),shades={top:createShade(),left:createShade().height(boundy),right:createShade().height(boundy),bottom:createShade()};function resizeShades(w,h){shades.left.css({height:px(h)});shades.right.css({height:px(h)});}
function updateAuto()
{return updateShade(Coords.getFixed());}
function updateShade(c)
{shades.top.css({left:px(c.x),width:px(c.w),height:px(c.y)});shades.bottom.css({top:px(c.y2),left:px(c.x),width:px(c.w),height:px(boundy-c.y2)});shades.right.css({left:px(c.x2),width:px(boundx-c.x2)});shades.left.css({width:px(c.x)});}
function createShade(){return $('<div />').css({position:'absolute',backgroundColor:options.shadeColor||options.bgColor}).appendTo(holder);}
function enableShade(){if(!enabled){enabled=true;holder.insertBefore($img);updateAuto();Selection.setBgOpacity(1,0,1);$img2.hide();setBgColor(options.shadeColor||options.bgColor,1);if(Selection.isAwake())
{setOpacity(options.bgOpacity,1);}
else setOpacity(1,1);}}
function setBgColor(color,now){colorChangeMacro(getShades(),color,now);}
function disableShade(){if(enabled){holder.remove();$img2.show();enabled=false;if(Selection.isAwake()){Selection.setBgOpacity(options.bgOpacity,1,1);}else{Selection.setBgOpacity(1,1,1);Selection.disableHandles();}
colorChangeMacro($div,0,1);}}
function setOpacity(opacity,now){if(enabled){if(options.bgFade&&!now){holder.animate({opacity:1-opacity},{queue:false,duration:options.fadeTime});}
else holder.css({opacity:1-opacity});}}
function refreshAll(){options.shade?enableShade():disableShade();if(Selection.isAwake())setOpacity(options.bgOpacity);}
function getShades(){return holder.children();}
return{update:updateAuto,updateRaw:updateShade,getShades:getShades,setBgColor:setBgColor,enable:enableShade,disable:disableShade,resize:resizeShades,refresh:refreshAll,opacity:setOpacity};}());var Selection=(function(){var awake,hdep=370;var borders={};var handle={};var seehandles=false;var hhs=options.handleOffset;function insertBorder(type)
{var jq=$('<div />').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;}
function dragDiv(ord,zi)
{var jq=$('<div />').mousedown(createDragger(ord)).css({cursor:ord+'-resize',position:'absolute',zIndex:zi}).addClass('ord-'+ord);if(Touch.support){jq.bind('touchstart.jcrop',Touch.createDragger(ord));}
$hdl_holder.append(jq);return jq;}
function insertHandle(ord)
{var hs=options.handleSize;return dragDiv(ord,hdep++).css({top:px(-hhs+1),left:px(-hhs+1),opacity:options.handleOpacity}).width(hs).height(hs).addClass(cssClass('handle'));}
function insertDragbar(ord)
{var s=options.handleSize,h=s,w=s,t=hhs,l=hhs;switch(ord){case'n':case's':w='100%';break;case'e':case'w':h='100%';break;}
return dragDiv(ord,hdep++).width(w).height(h).css({top:px(-t+1),left:px(-l+1)});}
function createHandles(li)
{var i;for(i=0;i<li.length;i++){handle[li[i]]=insertHandle(li[i]);}}
function moveHandles(c)
{var midvert=Math.round((c.h/2)-hhs),midhoriz=Math.round((c.w/2)-hhs),north=-hhs+1,west=-hhs+1,east=c.w-hhs,south=c.h-hhs,x,y;if(handle.e){handle.e.css({top:px(midvert),left:px(east)});handle.w.css({top:px(midvert)});handle.s.css({top:px(south),left:px(midhoriz)});handle.n.css({left:px(midhoriz)});}
if(handle.ne){handle.ne.css({left:px(east)});handle.se.css({top:px(south),left:px(east)});handle.sw.css({top:px(south)});}
if(handle.b){handle.b.css({top:px(south)});handle.r.css({left:px(east)});}}
function moveto(x,y)
{if(!options.shade){$img2.css({top:px(-y),left:px(-x)});}
$sel.css({top:px(y),left:px(x)});}
function resize(w,h)
{$sel.width(w).height(h);}
function refresh()
{var c=Coords.getFixed();Coords.setPressed([c.x,c.y]);Coords.setCurrent([c.x2,c.y2]);updateVisible();}
function updateVisible(select)
{if(awake){return update(select);}}
function update(select)
{var c=Coords.getFixed();resize(c.w,c.h);moveto(c.x,c.y);if(options.shade)Shade.updateRaw(c);if(seehandles){moveHandles(c);}
if(!awake){show();}
if(select){options.onSelect.call(api,unscale(c));}else{options.onChange.call(api,unscale(c));}}
function setBgOpacity(opacity,force,now)
{if(!awake&&!force)return;if(options.bgFade&&!now){$img.animate({opacity:opacity},{queue:false,duration:options.fadeTime});}else{$img.css('opacity',opacity);}}
function show()
{$sel.show();if(options.shade)Shade.opacity(bgopacity);else setBgOpacity(bgopacity,true);awake=true;}
function release()
{disableHandles();$sel.hide();if(options.shade)Shade.opacity(1);else setBgOpacity(1);awake=false;options.onRelease.call(api);}
function showHandles()
{if(seehandles){moveHandles(Coords.getFixed());$hdl_holder.show();}}
function enableHandles()
{seehandles=true;if(options.allowResize){moveHandles(Coords.getFixed());$hdl_holder.show();return true;}}
function disableHandles()
{seehandles=false;$hdl_holder.hide();}
function animMode(v)
{if(animating===v){disableHandles();}else{enableHandles();}}
function done()
{animMode(false);refresh();}
if(options.drawBorders){borders={top:insertBorder('hline'),bottom:insertBorder('hline bottom'),left:insertBorder('vline'),right:insertBorder('vline right')};}
if(options.dragEdges){handle.t=insertDragbar('n');handle.b=insertDragbar('s');handle.r=insertDragbar('e');handle.l=insertDragbar('w');}
if(options.sideHandles){createHandles(['n','s','e','w']);}
if(options.cornerHandles){createHandles(['sw','nw','ne','se']);}
$(document).bind('touchstart.jcrop-ios',function(e){if($(e.currentTarget).hasClass('jcrop-tracker'))e.stopPropagation();});var $track=newTracker().mousedown(createDragger('move')).css({cursor:'move',position:'absolute',zIndex:360});if(Touch.support){$track.bind('touchstart.jcrop',Touch.createDragger('move'));}
$img_holder.append($track);disableHandles();return{updateVisible:updateVisible,update:update,release:release,refresh:refresh,isAwake:function(){return awake;},setCursor:function(cursor){$track.css('cursor',cursor);},enableHandles:enableHandles,enableOnly:function(){seehandles=true;},showHandles:showHandles,disableHandles:disableHandles,animMode:animMode,setBgOpacity:setBgOpacity,done:done};}());var Tracker=(function(){var onMove=function(){},onDone=function(){},trackDoc=options.trackDocument;function toFront()
{$trk.css({zIndex:450});if(Touch.support){$(document).bind('touchmove.jcrop',trackTouchMove).bind('touchend.jcrop',trackTouchEnd);}
if(trackDoc){$(document).bind('mousemove.jcrop',trackMove).bind('mouseup.jcrop',trackUp);}}
function toBack()
{$trk.css({zIndex:290});$(document).unbind('.jcrop');}
function trackMove(e)
{onMove(mouseAbs(e));return false;}
function trackUp(e)
{e.preventDefault();e.stopPropagation();if(btndown){btndown=false;onDone(mouseAbs(e));if(Selection.isAwake()){options.onSelect.call(api,unscale(Coords.getFixed()));}
toBack();onMove=function(){};onDone=function(){};}
return false;}
function activateHandlers(move,done)
{btndown=true;onMove=move;onDone=done;toFront();return false;}
function trackTouchMove(e)
{e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return trackMove(e);}
function trackTouchEnd(e)
{e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return trackUp(e);}
function setCursor(t)
{$trk.css('cursor',t);}
if(!trackDoc){$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);}
$img.before($trk);return{activateHandlers:activateHandlers,setCursor:setCursor};}());var KeyManager=(function(){var $keymgr=$('<input type="radio" />').css({position:'fixed',left:'-120px',width:'12px'}),$keywrap=$('<div />').css({position:'absolute',overflow:'hidden'}).append($keymgr);function watchKeys()
{if(options.keySupport){$keymgr.show();$keymgr.focus();}}
function onBlur(e)
{$keymgr.hide();}
function doNudge(e,x,y)
{if(options.allowMove){Coords.moveOffset([x,y]);Selection.updateVisible(true);}
e.preventDefault();e.stopPropagation();}
function parseKey(e)
{if(e.ctrlKey||e.metaKey){return true;}
shift_down=e.shiftKey?true:false;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break;case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:if(options.allowSelect)Selection.release();break;case 9:return true;}
return false;}
if(options.keySupport){$keymgr.keydown(parseKey).blur(onBlur);if(ie6mode||!options.fixedSupport){$keymgr.css({position:'absolute',left:'-20px'});$keywrap.append($keymgr).insertBefore($img);}else{$keymgr.insertBefore($img);}}
return{watchKeys:watchKeys};}());function setClass(cname)
{$div.removeClass().addClass(cssClass('holder')).addClass(cname);}
function animateTo(a,callback)
{var x1=parseInt(a[0],10)/xscale,y1=parseInt(a[1],10)/yscale,x2=parseInt(a[2],10)/xscale,y2=parseInt(a[3],10)/yscale;if(animating){return;}
var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x=animat[0];y=animat[1];x2=animat[2];y2=animat[3];Selection.animMode(true);var anim_timer;function queueAnimator(){window.setTimeout(animator,interv);}
var animator=(function(){return function(){pcent+=(100-pcent)/velocity;animat[0]=x+((pcent/100)*ix1);animat[1]=y+((pcent/100)*iy1);animat[2]=x2+((pcent/100)*ix2);animat[3]=y2+((pcent/100)*iy2);if(pcent>=99.8){pcent=100;}
if(pcent<100){setSelectRaw(animat);queueAnimator();}else{Selection.done();if(typeof(callback)==='function'){callback.call(api);}}};}());queueAnimator();}
function setSelect(rect)
{setSelectRaw([parseInt(rect[0],10)/xscale,parseInt(rect[1],10)/yscale,parseInt(rect[2],10)/xscale,parseInt(rect[3],10)/yscale]);options.onSelect.call(api,unscale(Coords.getFixed()));Selection.enableHandles();}
function setSelectRaw(l)
{Coords.setPressed([l[0],l[1]]);Coords.setCurrent([l[2],l[3]]);Selection.update();}
function tellSelect()
{return unscale(Coords.getFixed());}
function tellScaled()
{return Coords.getFixed();}
function setOptionsNew(opt)
{setOptions(opt);interfaceUpdate();}
function disableCrop()
{options.disabled=true;Selection.disableHandles();Selection.setCursor('default');Tracker.setCursor('default');}
function enableCrop()
{options.disabled=false;interfaceUpdate();}
function cancelCrop()
{Selection.done();Tracker.activateHandlers(null,null);}
function destroy()
{$div.remove();$origimg.show();$(obj).removeData('Jcrop');}
function setImage(src,callback)
{Selection.release();disableCrop();var img=new Image();img.onload=function(){var iw=img.width;var ih=img.height;var bw=options.boxWidth;var bh=options.boxHeight;$img.width(iw).height(ih);$img.attr('src',src);$img2.attr('src',src);presize($img,bw,bh);boundx=$img.width();boundy=$img.height();$img2.width(boundx).height(boundy);$trk.width(boundx+(bound*2)).height(boundy+(bound*2));$div.width(boundx).height(boundy);Shade.resize(boundx,boundy);enableCrop();if(typeof(callback)==='function'){callback.call(api);}};img.src=src;}
function colorChangeMacro($obj,color,now){var mycolor=color||options.bgColor;if(options.bgFade&&supportsColorFade()&&options.fadeTime&&!now){$obj.animate({backgroundColor:mycolor},{queue:false,duration:options.fadeTime});}else{$obj.css('backgroundColor',mycolor);}}
function interfaceUpdate(alt)
{if(options.allowResize){if(alt){Selection.enableOnly();}else{Selection.enableHandles();}}else{Selection.disableHandles();}
Tracker.setCursor(options.allowSelect?'crosshair':'default');Selection.setCursor(options.allowMove?'move':'default');if(options.hasOwnProperty('trueSize')){xscale=options.trueSize[0]/boundx;yscale=options.trueSize[1]/boundy;}
if(options.hasOwnProperty('setSelect')){setSelect(options.setSelect);Selection.done();delete(options.setSelect);}
Shade.refresh();if(options.bgColor!=bgcolor){colorChangeMacro(options.shade?Shade.getShades():$div,options.shade?(options.shadeColor||options.bgColor):options.bgColor);bgcolor=options.bgColor;}
if(bgopacity!=options.bgOpacity){bgopacity=options.bgOpacity;if(options.shade)Shade.refresh();else Selection.setBgOpacity(bgopacity);}
xlimit=options.maxSize[0]||0;ylimit=options.maxSize[1]||0;xmin=options.minSize[0]||0;ymin=options.minSize[1]||0;if(options.hasOwnProperty('outerImage')){$img.attr('src',options.outerImage);delete(options.outerImage);}
Selection.refresh();}
if(Touch.support)$trk.bind('touchstart.jcrop',Touch.newSelection);$hdl_holder.hide();interfaceUpdate(true);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale];},getWidgetSize:function(){return[boundx,boundy];},getScaleFactor:function(){return[xscale,yscale];},ui:{holder:$div,selection:$sel}};if($.browser.msie){$div.bind('selectstart',function(){return false;});}
$origimg.data('Jcrop',api);return api;};$.fn.Jcrop=function(options,callback)
{var api;this.each(function(){if($(this).data('Jcrop')){if(options==='api')return $(this).data('Jcrop');else $(this).data('Jcrop').setOptions(options);}
else{if(this.tagName=='IMG')
$.Jcrop.Loader(this,function(){$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);});else{$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);}}});return this;};$.Jcrop.Loader=function(imgobj,success,error){var $img=$(imgobj),img=$img[0];function completeCheck(){if(img.complete){$img.unbind('.jcloader');if($.isFunction(success))success.call(img);}
else window.setTimeout(completeCheck,50);}
$img.bind('load.jcloader',completeCheck).bind('error.jcloader',function(e){$img.unbind('.jcloader');if($.isFunction(error))error.call(img);});if(img.complete&&$.isFunction(success)){$img.unbind('.jcloader');success.call(img);}};$.Jcrop.defaults={allowSelect:true,allowMove:true,allowResize:true,trackDocument:true,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:0.6,bgFade:false,borderOpacity:0.4,handleOpacity:0.5,handleSize:7,handleOffset:5,aspectRatio:0,keySupport:true,cornerHandles:true,sideHandles:true,drawBorders:true,dragEdges:true,fixedSupport:true,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}};}(jQuery));

863
js/jquery.jec-1.3.3.js Normal file
View File

@ -0,0 +1,863 @@
/**
* jQuery jEC (jQuery Editable Combobox) 1.3.3
* http://code.google.com/p/jquery-jec
*
* Copyright (c) 2008-2009 Lukasz Rajchel (lukasz@rajchel.pl | http://rajchel.pl)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Documentation : http://code.google.com/p/jquery-jec/wiki/Documentation
* Changelog : http://code.google.com/p/jquery-jec/wiki/Changelog
*
* Contributors : Lukasz Rajchel, Artem Orlov
*/
/*jslint maxerr: 50, indent: 4, maxlen: 120*/
/*global Array, Math, String, clearInterval, document, jQuery, setInterval*/
/*members ':', Handle, Remove, Set, acceptedKeys, addClass, all, append, appendTo, array, attr, before, bind,
blinkingCursor, blinkingCursorInterval, blur, bool, browser, ceil, change, charCode, classes, clearCursor, click, css,
cursorState, data, destroy, disable, each, editable, enable, eq, expr, extend, filter, find, floor, fn, focus,
focusOnNewOption, fromCharCode, get, getId, handleCursor, ignoredKeys, ignoreOptGroups, inArray, init, initJS, integer,
isArray, isPlainObject, jEC, jECTimer, jec, jecKill, jecOff, jecOn, jecPref, jecValue, keyCode, keyDown, keyPress,
keyRange, keyUp, keys, length, max, maxLength, min, msie, object, openedState, optionClasses, optionStyles, parent,
position, pref, prop, push, random, remove, removeAttr, removeClass, removeData, removeProp, safari, setEditableOption,
styles, substring, text, trigger, triggerChangeEvent, unbind, uneditable, useExistingOptions, val, value,
valueIsEditable, which*/
(function ($) {
'use strict';
$.jEC = (function () {
var pluginClass = 'jecEditableOption', cursorClass = 'hasCursor', options = {}, values = {}, lastKeyCode,
defaults, Validators, EventHandlers, Combobox, activeCombobox;
if ($.fn.prop === undefined) {
$.fn.extend({
'prop': function (key, valueSet) {
if (valueSet) {
$(this).attr(key, key);
} else {
$(this).removeAttr(key);
}
},
'removeProp': function (key) {
$(this).removeAttr(key);
}
});
}
defaults = {
position: 0,
ignoreOptGroups: false,
maxLength: 255,
classes: [],
styles: {},
optionClasses: [],
optionStyles: {},
triggerChangeEvent: false,
focusOnNewOption: false,
useExistingOptions: false,
blinkingCursor: false,
blinkingCursorInterval: 1000,
ignoredKeys: [],
acceptedKeys: [[32, 126], [191, 382]]
};
Validators = (function () {
return {
integer: function (value) {
return typeof value === 'number' && Math.ceil(value) === Math.floor(value);
},
keyRange: function (value) {
var min, max;
if ($.isPlainObject(value)) {
min = value.min;
max = value.max;
} else if ($.isArray(value) && value.length === 2) {
min = value[0];
max = value[1];
}
return Validators.integer(min) && Validators.integer(max) && min <= max;
}
};
}());
EventHandlers = (function () {
var getKeyCode;
getKeyCode = function (event) {
var charCode = event.charCode;
if (charCode !== undefined && charCode !== 0) {
return charCode;
} else {
return event.keyCode;
}
};
return {
// focus event handler
// enables blinking cursor
focus: function () {
var opt = options[Combobox.getId($(this))];
if (opt.blinkingCursor && $.jECTimer === undefined) {
activeCombobox = $(this);
$.jECTimer = setInterval($.jEC.handleCursor, opt.blinkingCursorInterval);
}
},
// blur event handler
// disables blinking cursor
blur: function () {
if ($.jECTimer !== undefined) {
clearInterval($.jECTimer);
$.jECTimer = undefined;
activeCombobox = undefined;
Combobox.clearCursor($(this));
}
Combobox.openedState($(this), false);
},
// keydown event handler
// handles keys pressed on select (backspace and delete must be handled
// in keydown event in order to work in IE)
keyDown: function (event) {
var keyCode = getKeyCode(event), option, value;
lastKeyCode = keyCode;
switch (keyCode) {
case 8: // backspace
case 46: // delete
option = $(this).find('option.' + pluginClass);
if (option.val().length >= 1) {
value = option.text().substring(0, option.text().length - 1);
option.val(value).text(value).prop('selected', true);
}
return (keyCode !== 8);
default:
break;
}
},
// keypress event handler
// handles the rest of the keys (keypress event gives more informations
// about pressed keys)
keyPress: function (event) {
var keyCode = getKeyCode(event), opt = options[Combobox.getId($(this))],
option, value, specialKeys, exit = false, text;
Combobox.clearCursor($(this));
if (keyCode !== 9 && keyCode !== 13 && keyCode !== 27) {
// special keys codes
specialKeys = [37, 38, 39, 40, 46];
// handle special keys
$.each(specialKeys, function (i, val) {
if (keyCode === val && keyCode === lastKeyCode) {
exit = true;
}
});
// don't handle ignored keys
if (!exit && $.inArray(keyCode, opt.ignoredKeys) === -1) {
// remove selection from all options
$(this).find('option:selected').removeProp('selected');
if ($.inArray(keyCode, opt.acceptedKeys) !== -1) {
option = $(this).find('option.' + pluginClass);
text = option.text();
if (text.length < opt.maxLength) {
value = text + String.fromCharCode(getKeyCode(event));
option.val(value).text(value);
}
option.prop('selected', true);
}
}
return false;
}
},
keyUp: function () {
var opt = options[Combobox.getId($(this))];
if (opt.triggerChangeEvent) {
$(this).trigger('change');
}
},
// change event handler
// handles editable option changing based on a pre-existing values
change: function () {
var opt = options[Combobox.getId($(this))];
if (opt.useExistingOptions) {
Combobox.setEditableOption($(this));
}
},
click: function () {
if (!$.browser.safari) {
Combobox.openedState($(this), !Combobox.openedState($(this)));
}
}
};
}());
// Combobox
Combobox = (function () {
var Parameters, EditableOption, generateId, setup;
// validates and set combobox parameters
Parameters = (function () {
var Set, Remove, Handle;
Set = (function () {
var parseKeys, Handles;
parseKeys = function (value) {
var keys = [];
if ($.isArray(value)) {
$.each(value, function (i, val) {
var j, min, max;
if (Validators.keyRange(val)) {
if ($.isArray(val)) {
min = val[0];
max = val[1];
} else {
min = val.min;
max = val.max;
}
for (j = min; j <= max; j += 1) {
keys.push(j);
}
} else if (typeof val === 'number' && Validators.integer(val)) {
keys.push(val);
}
});
}
return keys;
};
Handles = (function () {
return {
integer: function (elem, name, value) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && Validators.integer(value)) {
opt[name] = value;
return true;
}
return false;
},
bool: function (elem, name, value) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && typeof value === 'boolean') {
opt[name] = value;
return true;
}
return false;
},
array: function (elem, name, value) {
if (typeof value === 'string') {
value = [value];
}
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && $.isArray(value)) {
opt[name] = value;
return true;
}
return false;
},
object: function (elem, name, value) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && value !== null && $.isPlainObject(value)) {
opt[name] = value;
}
},
keys: function (elem, name, value) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && $.isArray(value)) {
opt[name] = parseKeys(value);
}
}
};
}());
return {
position: function (elem, value) {
if (Handles.integer(elem, 'position', value)) {
var id = Combobox.getId(elem), opt = options[id], optionsCount;
optionsCount =
elem.find('option:not(.' + pluginClass + ')').length;
if (value > optionsCount) {
opt.position = optionsCount;
}
}
},
ignoreOptGroups: function (elem, value) {
Handles.bool(elem, 'ignoreOptGroups', value);
},
maxLength: function (elem, value) {
if (Handles.integer(elem, 'maxLength', value)) {
var id = Combobox.getId(elem), opt = options[id];
if (value < 0 || value > 255) {
opt.maxLength = 255;
}
}
},
classes: function (elem, value) {
Handles.array(elem, 'classes', value);
},
optionClasses: function (elem, value) {
Handles.array(elem, 'optionClasses', value);
},
styles: function (elem, value) {
Handles.object(elem, 'styles', value);
},
optionStyles: function (elem, value) {
Handles.object(elem, 'optionStyles', value);
},
triggerChangeEvent: function (elem, value) {
Handles.bool(elem, 'triggerChangeEvent', value);
},
focusOnNewOption: function (elem, value) {
Handles.bool(elem, 'focusOnNewOption', value);
},
useExistingOptions: function (elem, value) {
Handles.bool(elem, 'useExistingOptions', value);
},
blinkingCursor: function (elem, value) {
Handles.bool(elem, 'blinkingCursor', value);
},
blinkingCursorInterval: function (elem, value) {
Handles.integer(elem, 'blinkingCursorInterval', value);
},
ignoredKeys: function (elem, value) {
Handles.keys(elem, 'ignoredKeys', value);
},
acceptedKeys: function (elem, value) {
Handles.keys(elem, 'acceptedKeys', value);
}
};
}());
Remove = (function () {
var removeClasses, removeStyles;
removeClasses = function (elem, classes) {
$.each(classes, function (i, val) {
elem.removeClass(val);
});
};
removeStyles = function (elem, styles) {
$.each(styles, function (key) {
elem.css(key, '');
});
};
return {
classes: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
removeClasses(elem, opt.classes);
}
},
optionClasses: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
removeClasses(elem.find('option.' + pluginClass),
opt.optionClasses);
}
},
styles: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
removeStyles(elem, opt.styles);
}
},
optionStyles: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
removeStyles(elem.find('option.' + pluginClass),
opt.optionStyles);
}
},
all: function (elem) {
Remove.classes(elem);
Remove.optionClasses(elem);
Remove.styles(elem);
Remove.optionStyles(elem);
}
};
}());
Handle = (function () {
var setClasses, setStyles;
setClasses = function (elem, classes) {
$.each(classes, function (i, val) {
elem.addClass(String(val));
});
};
setStyles = function (elem, styles) {
$.each(styles, function (key, val) {
elem.css(key, val);
});
};
return {
position: function (elem) {
var opt = options[Combobox.getId(elem)], option, uneditableOptions, container;
option = elem.find('option.' + pluginClass);
uneditableOptions = elem.find('option:not(.' + pluginClass + ')');
if (opt.position < uneditableOptions.length) {
container = uneditableOptions.eq(opt.position);
if (!opt.ignoreOptGroups && container.parent('optgroup').length > 0) {
uneditableOptions.eq(opt.position).parent().before(option);
} else {
uneditableOptions.eq(opt.position).before(option);
}
} else {
elem.append(option);
}
},
classes: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
setClasses(elem, opt.classes);
}
},
optionClasses: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
setClasses(elem.find('option.' + pluginClass), opt.optionClasses);
}
},
styles: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
setStyles(elem, opt.styles);
}
},
optionStyles: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined) {
setStyles(elem.find('option.' + pluginClass), opt.optionStyles);
}
},
focusOnNewOption: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && opt.focusOnNewOption) {
elem.find(':not(option.' + pluginClass + ')').removeProp('selected');
elem.find('option.' + pluginClass).prop('selected', true);
}
},
useExistingOptions: function (elem) {
var id = Combobox.getId(elem), opt = options[id];
if (opt !== undefined && opt.useExistingOptions) {
Combobox.setEditableOption(elem);
}
},
all: function (elem) {
Handle.position(elem);
Handle.classes(elem);
Handle.optionClasses(elem);
Handle.styles(elem);
Handle.optionStyles(elem);
Handle.focusOnNewOption(elem);
Handle.useExistingOptions(elem);
}
};
}());
return {
Set: Set,
Remove: Remove,
Handle: Handle
};
}());
EditableOption = (function () {
return {
init: function (elem) {
if (!elem.find('option.' + pluginClass).length) {
var editableOption = $('<option>');
editableOption.addClass(pluginClass);
elem.append(editableOption);
}
elem.bind('keydown', EventHandlers.keyDown);
elem.bind('keypress', EventHandlers.keyPress);
elem.bind('keyup', EventHandlers.keyUp);
elem.bind('change', EventHandlers.change);
elem.bind('focus', EventHandlers.focus);
elem.bind('blur', EventHandlers.blur);
elem.bind('click', EventHandlers.click);
},
destroy: function (elem) {
elem.find('option.' + pluginClass).remove();
elem.unbind('keydown', EventHandlers.keyDown);
elem.unbind('keypress', EventHandlers.keyPress);
elem.unbind('keyup', EventHandlers.keyUp);
elem.unbind('change', EventHandlers.change);
elem.unbind('focus', EventHandlers.focus);
elem.unbind('blur', EventHandlers.blur);
elem.unbind('click', EventHandlers.click);
}
};
}());
// generates unique identifier
generateId = function () {
while (true) {
var random = Math.floor(Math.random() * 100000);
if (options[random] === undefined) {
return random;
}
}
};
// sets combobox
setup = function (elem) {
EditableOption.init(elem);
Parameters.Handle.all(elem);
};
// Combobox public members
return {
// create editable combobox
init: function (settings) {
return $(this).filter(':uneditable').each(function () {
var id = generateId(), elem = $(this);
elem.data('jecId', id);
// override passed default options
options[id] = $.extend(true, {}, defaults);
// parse keys
Parameters.Set.ignoredKeys(elem, options[id].ignoredKeys);
Parameters.Set.acceptedKeys(elem, options[id].acceptedKeys);
if ($.isPlainObject(settings)) {
$.each(settings, function (key, val) {
if (val !== undefined) {
switch (key) {
case 'position':
Parameters.Set.position(elem, val);
break;
case 'ignoreOptGroups':
Parameters.Set.ignoreOptGroups(elem, val);
break;
case 'maxLength':
Parameters.Set.maxLength(elem, val);
break;
case 'classes':
Parameters.Set.classes(elem, val);
break;
case 'optionClasses':
Parameters.Set.optionClasses(elem, val);
break;
case 'styles':
Parameters.Set.styles(elem, val);
break;
case 'optionStyles':
Parameters.Set.optionStyles(elem, val);
break;
case 'triggerChangeEvent':
Parameters.Set.triggerChangeEvent(elem, val);
break;
case 'focusOnNewOption':
Parameters.Set.focusOnNewOption(elem, val);
break;
case 'useExistingOptions':
Parameters.Set.useExistingOptions(elem, val);
break;
case 'blinkingCursor':
Parameters.Set.blinkingCursor(elem, val);
break;
case 'blinkingCursorInterval':
Parameters.Set.blinkingCursorInterval(elem, val);
break;
case 'ignoredKeys':
Parameters.Set.ignoredKeys(elem, val);
break;
case 'acceptedKeys':
Parameters.Set.acceptedKeys(elem, val);
break;
}
}
});
}
setup($(this));
});
},
// creates editable combobox without using existing select elements
initJS: function (options, settings) {
var select, addOptions;
select = $('<select>');
addOptions = function (elem, options) {
if ($.isArray(options)) {
$.each(options, function (i, val) {
if ($.isPlainObject(val)) {
$.each(val, function (key, value) {
if ($.isArray(value)) {
var og = $('<optgroup>').attr('label', key);
addOptions(og, value);
og.appendTo(select);
} else if (typeof value === 'number' || typeof value === 'string') {
$('<option>').text(value).attr('value', key)
.appendTo(elem);
}
});
} else if (typeof val === 'string' || typeof val === 'number') {
$('<option>').text(val).attr('value', val).appendTo(elem);
}
});
}
};
addOptions(select, options);
return select.jec(settings);
},
// destroys editable combobox
destroy: function () {
return $(this).filter(':editable').each(function () {
$(this).jecOff();
$.removeData($(this).get(0), 'jecId');
$.removeData($(this).get(0), 'jecCursorState');
$.removeData($(this).get(0), 'jecOpenedState');
});
},
// enable editablecombobox
enable: function () {
return $(this).filter(':editable').each(function () {
var id = Combobox.getId($(this)), value = values[id];
setup($(this));
if (value !== undefined) {
$(this).jecValue(value);
}
});
},
// disable editable combobox
disable: function () {
return $(this).filter(':editable').each(function () {
var val = $(this).find('option.' + pluginClass).val();
values[Combobox.getId($(this))] = val;
Parameters.Remove.all($(this));
EditableOption.destroy($(this));
});
},
// gets or sets editable option's value
value: function (value, setFocus) {
if ($(this).filter(':editable').length > 0) {
if (value === null || value === undefined) {
// get value
return $(this).find('option.' + pluginClass).val();
} else if (typeof value === 'string' || typeof value === 'number') {
// set value
return $(this).filter(':editable').each(function () {
var option = $(this).find('option.' + pluginClass);
option.val(value).text(value);
if (typeof setFocus !== 'boolean' || setFocus) {
option.prop('selected', true);
}
});
}
}
},
// gets or sets editable option's preference
pref: function (name, value) {
if ($(this).filter(':editable').length > 0) {
if (typeof name === 'string') {
if (value === null || value === undefined) {
// get preference
return options[Combobox.getId($(this))][name];
} else {
// set preference
return $(this).filter(':editable').each(function () {
switch (name) {
case 'position':
Parameters.Set.position($(this), value);
Parameters.Handle.position($(this));
break;
case 'classes':
Parameters.Remove.classes($(this));
Parameters.Set.classes($(this), value);
Parameters.Handle.position($(this));
break;
case 'optionClasses':
Parameters.Remove.optionClasses($(this));
Parameters.Set.optionClasses($(this), value);
Parameters.Set.optionClasses($(this));
break;
case 'styles':
Parameters.Remove.styles($(this));
Parameters.Set.styles($(this), value);
Parameters.Set.styles($(this));
break;
case 'optionStyles':
Parameters.Remove.optionStyles($(this));
Parameters.Set.optionStyles($(this), value);
Parameters.Handle.optionStyles($(this));
break;
case 'focusOnNewOption':
Parameters.Set.focusOnNewOption($(this), value);
Parameters.Handle.focusOnNewOption($(this));
break;
case 'useExistingOptions':
Parameters.Set.useExistingOptions($(this), value);
Parameters.Handle.useExistingOptions($(this));
break;
case 'blinkingCursor':
Parameters.Set.blinkingCursor($(this), value);
break;
case 'blinkingCursorInterval':
Parameters.Set.blinkingCursorInterval($(this), value);
break;
case 'ignoredKeys':
Parameters.Set.ignoredKeys($(this), value);
break;
case 'acceptedKeys':
Parameters.Set.acceptedKeys($(this), value);
break;
}
});
}
}
}
},
// sets editable option to the value of currently selected option
setEditableOption: function (elem) {
var value = elem.find('option:selected').text();
elem.find('option.' + pluginClass).attr('value', elem.val()).text(value).prop('selected', true);
},
// get combobox id
getId: function (elem) {
return elem.data('jecId');
},
valueIsEditable: function (elem) {
return elem.find('option.' + pluginClass).get(0) === elem.find('option:selected').get(0);
},
clearCursor: function (elem) {
$(elem).find('option.' + cursorClass).each(function () {
var text = $(this).text();
$(this).removeClass(cursorClass).text(text.substring(0, text.length - 1));
});
},
cursorState: function (elem, state) {
return elem.data('jecCursorState', state);
},
openedState: function (elem, state) {
return elem.data('jecOpenedState', state);
},
//handles editable cursor
handleCursor: function () {
if (activeCombobox !== undefined && activeCombobox !== null) {
if ($.browser.msie && Combobox.openedState(activeCombobox)) {
return;
}
var state = Combobox.cursorState(activeCombobox), elem;
if (state) {
Combobox.clearCursor(activeCombobox);
} else if (Combobox.valueIsEditable(activeCombobox)) {
elem = activeCombobox.find('option:selected');
elem.addClass(cursorClass).text(elem.text() + '|');
}
Combobox.cursorState(activeCombobox, !state);
}
}
};
}());
// jEC public members
return {
init: Combobox.init,
enable: Combobox.enable,
disable: Combobox.disable,
destroy: Combobox.destroy,
value: Combobox.value,
pref: Combobox.pref,
initJS: Combobox.initJS,
handleCursor: Combobox.handleCursor
};
}());
// register functions
$.fn.extend({
jec: $.jEC.init,
jecOn: $.jEC.enable,
jecOff: $.jEC.disable,
jecKill: $.jEC.destroy,
jecValue: $.jEC.value,
jecPref: $.jEC.pref
});
$.extend({
jec: $.jEC.initJS
});
// register selectors
$.extend($.expr[':'], {
editable: function (a) {
var data = $(a).data('jecId');
return data !== null && data !== undefined;
},
uneditable: function (a) {
var data = $(a).data('jecId');
return data === null || data === undefined;
}
});
}(jQuery));

27
templates/index2.php Normal file
View File

@ -0,0 +1,27 @@
<script type='text/javascript'>
var totalurl = '<?php echo OC_Helper::linkTo('contacts', 'carddav.php', null, true); ?>/addressbooks';
</script>
<div id="controls">
<form>
<input type="button" id="contacts_newcontact" value="<?php echo $l->t('Add Contact'); ?>">
<input type="button" id="chooseaddressbook" value="<?php echo $l->t('Addressbooks'); ?>">
</form>
</div>
<div id="leftcontent" class="leftcontent">
<ul id="contacts">
<?php echo $this->inc("part.contacts"); ?>
</ul>
</div>
<div id="rightcontent" class="rightcontent" data-id="<?php echo $_['id']; ?>">
<?php
if ($_['id']){
echo $this->inc('part.contact');
}
else{
echo $this->inc('part.no_contacts');
}
?>
</div>
<!-- Dialogs -->
<div id="dialog_holder"></div>
<!-- End of Dialogs -->

210
templates/part.contact.php Normal file
View File

@ -0,0 +1,210 @@
<?php
$l=new OC_L10N('contacts');
$id = isset($_['id']) ? $_['id'] : '';
$card = array();
$card['id'] = $id;
$card['FN'] = (array_key_exists('FN',$_['details'])) ? $_['details']['FN'][0] : null;
$card['N'] = (array_key_exists('N',$_['details'])) ? $_['details']['N'][0] : array('', '', '', '', '');
$card['ORG'] = (array_key_exists('ORG',$_['details'])) ? $_['details']['ORG'][0] : null;
$card['PHOTO'] = (array_key_exists('PHOTO',$_['details'])) ? $_['details']['PHOTO'][0] : null;
$card['BDAY'] = (array_key_exists('BDAY',$_['details'])) ? $_['details']['BDAY'][0] : null;
if($card['BDAY']) {
$bday = new DateTime($card['BDAY']['value']);
$card['BDAY']['value'] = $bday->format('d-m-Y');
}
$card['NICKNAME'] = (array_key_exists('NICKNAME',$_['details'])) ? $_['details']['NICKNAME'][0] : null;
$card['EMAIL'] = (array_key_exists('EMAIL',$_['details'])) ? $_['details']['EMAIL'] : array();
$card['TEL'] = (array_key_exists('TEL',$_['details'])) ? $_['details']['TEL'] : array();
$card['ADR'] = (array_key_exists('ADR',$_['details'])) ? $_['details']['ADR'] : array();
?>
<div id="card">
<div id="actionbar">
<a id="contacts_propertymenu_button"></a>
<ul id="contacts_propertymenu">
<li <?php echo (!is_null($card['PHOTO'])?'style="display:none;"':''); ?>>
<a data-type="PHOTO"><?php echo $l->t('Profile picture'); ?></a>
</li>
<li <?php echo (!is_null($card['ORG'])?'style="display:none;"':''); ?>>
<a data-type="ORG"><?php echo $l->t('Organization'); ?></a>
</li>
<li <?php echo (!is_null($card['NICKNAME'])?'style="display:none;"':''); ?>>
<a data-type="NICKNAME"><?php echo $l->t('Nickname'); ?></a>
</li>
<li <?php echo (!is_null($card['BDAY'])?'style="display:none;"':''); ?>>
<a data-type="BDAY"><?php echo $l->t('Birthday'); ?></a>
</li>
<li><a data-type="TEL"><?php echo $l->t('Phone'); ?></a></li>
<li><a data-type="EMAIL"><?php echo $l->t('Email'); ?></a></li>
<li><a data-type="ADR"><?php echo $l->t('Address'); ?></a></li>
</ul>
<img onclick="Contacts.UI.Card.export();" class="svg action" id="contacts_downloadcard" src="<?php echo image_path('', 'actions/download.svg'); ?>" title="<?php echo $l->t('Download contact');?>" />
<img class="svg action" id="contacts_deletecard" src="<?php echo image_path('', 'actions/delete.svg'); ?>" title="<?php echo $l->t('Delete contact');?>" />
</div>
<div class="contactsection">
<form <?php echo (is_null($card['PHOTO'])?'style="display:none;"':''); ?> id="file_upload_form" action="ajax/uploadphoto.php" method="post" enctype="multipart/form-data" target="file_upload_target">
<fieldset id="photo" class="formfloat">
<div id="contacts_details_photo_wrapper" title="<?php echo $l->t('Click or drop to upload picture'); ?> (max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
<!-- img style="padding: 1em;" id="contacts_details_photo" alt="Profile picture" src="photo.php?id=<?php echo $_['id']; ?>" / -->
<progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress>
</div>
<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload">
<input type="hidden" class="max_human_file_size" value="(max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
<input id="file_upload_start" type="file" accept="image/*" name="imagefile" />
<iframe name="file_upload_target" id='file_upload_target' src=""></iframe>
</fieldset>
</form>
<form id="contact_identity" method="post" <?php echo ($_['id']==''||!isset($_['id'])?'style="display:none;"':''); ?>>
<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
<fieldset class="propertycontainer" data-element="N"><input type="hidden" id="n" class="contacts_property" name="value" value="" /></fieldset>
<fieldset id="ident" class="formfloat">
<!-- legend>Name</legend -->
<dl class="form">
<!-- dt><label for="n"><?php echo $l->t('Name'); ?></label></dt>
<dd style="padding-top: 0.8em;vertical-align: text-bottom;"><span id="n" type="text"></span></dd -->
<dt><label for="fn"><?php echo $l->t('Display name'); ?></label></dt>
<dd class="propertycontainer" data-element="FN">
<select id="fn" name="value" required="required" class="contacts_property" title="<?php echo $l->t('Format custom, Short name, Full name, Reverse or Reverse with comma'); ?>" style="width:16em;">
<option id="short" title="Short name"></option>
<option id="full" title="Full name"></option>
<option id="reverse" title="Reverse"></option>
<option id="reverse_comma" title="Reverse with comma"></option>
</select><a id="edit_name" class="edit" title="<?php echo $l->t('Edit name details'); ?>"></a>
</dd>
<dt style="display:none;" id="org_label" data-element="ORG"><label for="org"><?php echo $l->t('Organization'); ?></label></dt>
<dd style="display:none;" class="propertycontainer" id="org_value" data-element="ORG"><input id="org" required="required" name="value[ORG]" type="text" class="contacts_property" style="width:16em;" name="value" value="" placeholder="<?php echo $l->t('Organization'); ?>" /><a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
<dt style="display:none;" id="nickname_label" data-element="NICKNAME"><label for="nickname"><?php echo $l->t('Nickname'); ?></label></dt>
<dd style="display:none;" class="propertycontainer" id="nickname_value" data-element="NICKNAME"><input id="nickname" required="required" name="value[NICKNAME]" type="text" class="contacts_property" style="width:16em;" name="value" value="" placeholder="<?php echo $l->t('Enter nickname'); ?>" /><a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
<dt style="display:none;" id="bday_label" data-element="BDAY"><label for="bday"><?php echo $l->t('Birthday'); ?></label></dt>
<dd style="display:none;" class="propertycontainer" id="bday_value" data-element="BDAY"><input id="bday" required="required" name="value" type="text" class="contacts_property" value="" placeholder="<?php echo $l->t('dd-mm-yyyy'); ?>" /><a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
</dl>
</fieldset>
</form>
</div>
<!-- div class="delimiter"></div -->
<form id="contact_communication" method="post">
<div class="contactsection">
<!-- email addresses -->
<div id="emails" <?php echo (count($card['EMAIL'])>0?'':'style="display:none;"'); ?>>
<fieldset class="contactpart">
<legend><?php echo $l->t('Email'); ?></legend>
<ul id="emaillist" class="propertylist">
<li class="template" style="white-space: nowrap; display: none;" data-element="EMAIL">
<input type="checkbox" class="contacts_property" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" />
<input type="email" required="required" class="nonempty contacts_property" style="width:15em;" name="value" value="" x-moz-errormessage="<?php echo $l->t('Please specify a valid email address.'); ?>" placeholder="<?php echo $l->t('Enter email address'); ?>" /><span class="listactions"><a onclick="Contacts.UI.mailTo(this)" class="mail" title="<?php echo $l->t('Mail to address'); ?>"></a>
<a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete email address'); ?>"></a></span></li>
<?php
if(0) { /*foreach($card['EMAIL'] as $email) {*/
?>
<li class="propertycontainer" style="white-space: nowrap;" data-checksum="<?php echo $email['checksum'] ?>" data-element="EMAIL">
<input type="checkbox" class="contacts_property" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" <?php echo (isset($email['parameters']['PREF'])?'checked="checked"':''); ?> />
<input type="email" required="required" class="nonempty contacts_property" style="width:15em;" name="value" value="<?php echo $email['value'] ?>" placeholder="<?php echo $l->t('Enter email address'); ?>" /><span class="listactions"><a onclick="Contacts.UI.mailTo(this)" class="mail" title="<?php echo $l->t('Mail to address'); ?>"></a>
<a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete email address'); ?>"></a></span></li>
<?php } ?>
</ul><!-- a id="add_email" class="add" title="<?php echo $l->t('Add email address'); ?>"></a -->
</div> <!-- email addresses-->
<!-- Phone numbers -->
<div id="phones" <?php echo (count($card['TEL'])>0?'':'style="display:none;"'); ?>>
<fieldset class="contactpart">
<legend><?php echo $l->t('Phone'); ?></legend>
<ul id="phonelist" class="propertylist">
<li class="template" style="white-space: nowrap; display: none;" data-element="TEL">
<input type="checkbox" class="contacts_property" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" />
<input type="text" required="required" class="nonempty contacts_property" style="width:10em; border: 0px;" name="value" value="" placeholder="<?php echo $l->t('Enter phone number'); ?>" />
<select multiple="multiple" name="parameters[TYPE][]">
<?php echo html_select_options($_['phone_types'], array()) ?>
</select>
<a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete phone number'); ?>"></a></li>
<?php
if(0) { /*foreach($card['TEL'] as $phone) {*/
?>
<li class="propertycontainer" style="white-space: nowrap;" data-checksum="<?php echo $phone['checksum'] ?>" data-element="TEL">
<input type="checkbox" class="contacts_property" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" <?php echo (isset($phone['parameters']['PREF'])?'checked="checked"':''); ?> />
<input type="text" required="required" class="nonempty contacts_property" style="width:8em; border: 0px;" name="value" value="<?php echo $phone['value'] ?>" placeholder="<?php echo $l->t('Enter phone number'); ?>" />
<select class="contacts_property" multiple="multiple" name="parameters[TYPE][]">
<?php echo html_select_options($_['phone_types'], isset($phone['parameters']['TYPE'])?$phone['parameters']['TYPE']:array()) ?>
</select>
<a class="delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete phone number'); ?>"></a></li>
<?php } ?>
</ul><!-- a id="add_phone" class="add" title="<?php echo $l->t('Add phone number'); ?>"></a -->
</div> <!-- Phone numbers -->
<!-- Addresses -->
<div id="addresses" <?php echo (count($card['ADR'])>0?'':'style="display:none;"'); ?>>
<fieldset class="contactpart">
<legend><?php echo $l->t('Address'); ?></legend>
<div id="addressdisplay">
<dl class="addresscard template" style="display: none;" data-element="ADR"><dt>
<input class="adr contacts_property" name="value" type="hidden" value="" />
<input type="hidden" class="adr_type contacts_property" name="parameters[TYPE][]" value="" />
<span class="adr_type_label"></span><a class="globe" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.searchOSM(this);" title="<?php echo $l->t('View on map'); ?>"></a><a class="edit" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.editAddress(this, false);" title="<?php echo $l->t('Edit address details'); ?>"></a><a class="delete" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="Delete address"></a>
</dt><dd><ul class="addresslist"></ul></dd></dl>
<?php if(0) { /*foreach($card['ADR'] as $address) {*/ ?>
<dl class="addresscard propertycontainer" data-checksum="<?php echo $address['checksum']; ?>" data-element="ADR">
<dt>
<input class="adr contacts_property" name="value" type="hidden" value="<?php echo implode(';',$address['value']); ?>" />
<input type="hidden" class="adr_type contacts_property" name="parameters[TYPE][]" value="<?php echo strtoupper(implode(',',$address['parameters'])); ?>" />
<span class="adr_type_label">
<?php
if(count($address['parameters']) > 0) {
//array_walk($address['parameters'], ) Nah, this wont work...
$translated = array();
foreach($address['parameters'] as $type) {
$translated[] = $l->t(ucwords(strtolower($type)));
}
echo implode('/', $translated);
}
?></span><a class="globe" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.searchOSM(this);" title="<?php echo $l->t('View on map'); ?>"></a><a class="edit" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.editAddress(this, false);" title="<?php echo $l->t('Edit address details'); ?>"></a><a class="delete" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="Delete address"></a>
</dt>
<dd>
<ul class="addresslist">
<?php
$adr = $address['value'];
$tmp = ($adr[0]?'<li>'.$adr[0].'</li>':'');
$tmp .= ($adr[1]?'<li>'.$adr[1].'</li>':'');
$tmp .= ($adr[2]?'<li>'.$adr[2].'</li>':'');
$tmp .= ($adr[3]||$adr[5]?'<li>'.$adr[5].' '.$adr[3].'</li>':'');
$tmp .= ($adr[4]?'<li>'.$adr[4].'</li>':'');
$tmp .= ($adr[6]?'<li>'.$adr[6].'</li>':'');
echo $tmp;
?>
</ul>
</dd>
</dl>
<?php } ?>
</fieldset>
</div>
</div> <!-- Addresses -->
</div>
<!-- a id="add_address" onclick="Contacts.UI.Card.editAddress('new', true)" class="add" title="<?php echo $l->t('Add address'); ?>"></a -->
</div>
</form>
</div>
<div class="delimiter"></div>
<pre>
<?php /*print_r($card);*/ ?>
</pre>
<!-- div class="updatebar"><input type="button" value="Update" /></div -->
<div id="edit_photo_dialog" title="Edit photo">
<div id="edit_photo_dialog_img"></div>
</div>
<script language="Javascript">
$(document).ready(function(){
if('<?php echo $id; ?>'!='') {
$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':'<?php echo $id; ?>'},function(jsondata){
if(jsondata.status == 'success'){
Contacts.UI.Card.loadContact(jsondata.data);
}
else{
Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message);
}
});
}
});
</script>

View File

@ -0,0 +1,9 @@
<?php
$id = $_['id'];
$wattr = isset($_['width'])?'width="'.$_['width'].'"':'';
$hattr = isset($_['height'])?'height="'.$_['height'].'"':'';
?>
<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OC_Helper::linkTo('contacts', 'photo.php', null, true); ?>?id=<?php echo $id; ?>&amp;refresh=<?php echo rand(); ?>" />
<progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress>

View File

@ -0,0 +1,62 @@
<?php
$id = $_['id'];
$tmp_path = $_['tmp_path'];
OC_Log::write('contacts','templates/part.cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
?>
<script language="Javascript">
jQuery(function($) {
$('#cropbox').Jcrop({
onChange: showCoords,
onSelect: showCoords,
onRelease: clearCoords,
maxSize: [399, 399],
bgColor: 'black',
bgOpacity: .4,
boxWidth: 400,
boxHeight: 400,
setSelect: [ 100, 130, 50, 50 ]//,
//aspectRatio: 0.8
});
});
// Simple event handler, called from onChange and onSelect
// event handlers, as per the Jcrop invocation above
function showCoords(c) {
$('#x1').val(c.x);
$('#y1').val(c.y);
$('#x2').val(c.x2);
$('#y2').val(c.y2);
$('#w').val(c.w);
$('#h').val(c.h);
};
function clearCoords() {
$('#coords input').val('');
};
/*
$('#coords').submit(function() {
alert('Handler for .submit() called.');
return true;
});*/
</script>
<img id="cropbox" src="<?php echo OC_Helper::linkTo('contacts', 'dynphoto.php', null, true); ?>?tmp_path=<?php echo urlencode($tmp_path); ?>" />
<form id="cropform"
class="coords"
method="post"
enctype="multipart/form-data"
target="crop_target"
action="<?php echo OC_Helper::linkTo('contacts', 'ajax/savecrop.php', null, true); ?>">
<input type="hidden" id="id" name="id" value="<?php echo $id; ?>" />
<input type="hidden" id="tmp_path" name="tmp_path" value="<?php echo $tmp_path; ?>" />
<fieldset id="coords">
<input type="hidden" id="x1" name="x1" value="" />
<input type="hidden" id="y1" name="y1" value="" />
<input type="hidden" id="x2" name="x2" value="" />
<input type="hidden" id="y2" name="y2" value="" />
<input type="hidden" id="w" name="w" value="" />
<input type="hidden" id="h" name="h" value="" />
</fieldset>
<iframe name="crop_target" id='crop_target' src=""></iframe>
</form>

View File

@ -0,0 +1,67 @@
<?php
$adr = isset($_['adr'])?$_['adr']:array();
$id = $_['id'];
$types = array();
foreach(isset($adr['parameters']['TYPE'])?array($adr['parameters']['TYPE']):array() as $type) {
$types[] = strtoupper($type);
}
?>
<div id="edit_address_dialog" title="<?php echo $l->t('Edit address'); ?>">
<!-- ?php print_r($types); ? -->
<fieldset id="address">
<dl class="form">
<dt>
<label class="label" for="adr_type"><?php echo $l->t('Type'); ?></label>
</dt>
<dd>
<select id="adr_type" name="parameters[ADR][TYPE]" size="1">
<?php echo html_select_options($_['adr_types'], $types) ?>
</select>
</dd>
<dt>
<label class="label" for="adr_pobox"><?php echo $l->t('PO Box'); ?></label>
</dt>
<dd>
<input type="text" id="adr_pobox" name="value[ADR][0]" value="<?php echo isset($adr['value'][0])?$adr['value'][0]:''; ?>">
</dd>
<dd>
<dt>
<label class="label" for="adr_extended"><?php echo $l->t('Extended'); ?></label>
</dt>
<dd>
<input type="text" id="adr_extended" name="value[ADR][1]" value="<?php echo isset($adr['value'][1])?$adr['value'][1]:''; ?>">
</dd>
<dt>
<label class="label" for="adr_street"><?php echo $l->t('Street'); ?></label>
</dt>
<dd>
<input type="text" id="adr_street" name="value[ADR][2]" value="<?php echo isset($adr['value'][2])?$adr['value'][2]:''; ?>">
</dd>
<dt>
<label class="label" for="adr_city"><?php echo $l->t('City'); ?></label>
</dt>
<dd>
<input type="text" id="adr_city" name="value[ADR][3]" value="<?php echo isset($adr['value'][3])?$adr['value'][3]:''; ?>">
</dd>
<dt>
<label class="label" for="adr_region"><?php echo $l->t('Region'); ?></label>
</dt>
<dd>
<input type="text" id="adr_region" name="value[ADR][4]" value="<?php echo isset($adr['value'][4])?$adr['value'][4]:''; ?>">
</dd>
<dt>
<label class="label" for="adr_zipcode"><?php echo $l->t('Zipcode'); ?></label>
</dt>
<dd>
<input type="text" id="adr_zipcode" name="value[ADR][5]" value="<?php echo isset($adr['value'][5])?$adr['value'][5]:''; ?>">
</dd>
<dt>
<label class="label" for="adr_country"><?php echo $l->t('Country'); ?></label>
</dt>
<dd>
<input type="text" id="adr_country" name="value[ADR][6]" value="<?php echo isset($adr['value'][6])?$adr['value'][6]:''; ?>">
</dd>
</dl>
</fieldset>
</form>
</div>

View File

@ -0,0 +1,59 @@
<?php
$l=new OC_L10N('contacts');
$name = isset($_['name'])?$_['name']:'';
//print_r($name);
$id = isset($_['id'])?$_['id']:'';
$addressbooks = isset($_['addressbooks'])?$_['addressbooks']:null;
?>
<div id="edit_name_dialog" title="Edit name">
<form>
<fieldset>
<dl class="form">
<?php if(!is_null($addressbooks)) {
if(count($_['addressbooks'])==1) {
?>
<input type="hidden" id="aid" name="aid" value="<?php echo $_['addressbooks'][0]['id']; ?>">
<?php } else { ?>
<dt><label for="addressbook"><?php echo $l->t('Addressbook'); ?></label></dt>
<dd>
<select id="aid" name="aid" size="1">
<?php echo html_select_options($_['addressbooks'], null, array('value'=>'id', 'label'=>'displayname')); ?>
</select>
</dd>
<?php }} ?>
<dt><label for="pre"><?php echo $l->t('Hon. prefixes'); ?></label></dt>
<dd>
<input name="pre" id="pre" value="<?php echo isset($name['value'][3]) ? $name['value'][3] : ''; ?>" type="text" list="prefixes" />
<datalist id="prefixes">
<option value="<?php echo $l->t('Miss'); ?>">
<option value="<?php echo $l->t('Ms'); ?>">
<option value="<?php echo $l->t('Mr'); ?>">
<option value="<?php echo $l->t('Sir'); ?>">
<option value="<?php echo $l->t('Mrs'); ?>">
<option value="<?php echo $l->t('Dr'); ?>">
</datalist>
</dd>
<dt><label for="giv"><?php echo $l->t('Given name'); ?></label></dt>
<dd><input name="giv" id="giv" value="<?php echo isset($name['value'][1]) ? $name['value'][1] : ''; ?>" type="text" /></dd>
<dt><label for="add"><?php echo $l->t('Additional names'); ?></label></dt>
<dd><input name="add" id="add" value="<?php echo isset($name['value'][2]) ? $name['value'][2] : ''; ?>" type="text" /></dd>
<dt><label for="fam"><?php echo $l->t('Family name'); ?></label></dt>
<dd><input name="fam" id="fam" value="<?php echo isset($name['value'][0]) ? $name['value'][0] : ''; ?>" type="text" /></dd>
<dt><label for="suf"><?php echo $l->t('Hon. suffixes'); ?></label></dt>
<dd>
<input name="suf" id="suf" value="<?php echo isset($name['value'][4]) ? $name['value'][4] : ''; ?>" type="text" list="suffixes" />
<datalist id="suffixes">
<option value="<?php echo $l->t('J.D.'); ?>">
<option value="<?php echo $l->t('M.D.'); ?>">
<option value="<?php echo $l->t('D.O.'); ?>">
<option value="<?php echo $l->t('D.C.'); ?>">
<option value="<?php echo $l->t('Ph.D.'); ?>">
<option value="<?php echo $l->t('Esq.'); ?>">
<option value="<?php echo $l->t('Jr.'); ?>">
<option value="<?php echo $l->t('Sn.'); ?>">
</datalist>
</dd>
</dl>
</fieldset>
</form>
</div>

View File

@ -0,0 +1,8 @@
<div id="firstrun">
You have no contacts in your list.
<div id="selections">
<input type="button" value="Import contacts" onclick="Contacts.UI.Addressbooks.import()" />
<input type="button" value="Add contact" onclick="Contacts.UI.Card.add()" />
<input type="button" value="Edit addressbooks" onclick="Contacts.UI.Addressbooks.overview()" />
</div>
</div>