diff --git a/civicrm/CRM/Activity/DAO/Activity.php b/civicrm/CRM/Activity/DAO/Activity.php index 5cbc7a0d8c3357a067fdfbc14b419aa6e8a99e6a..26a5ec64c860989627f6facc803209e501a90f37 100644 --- a/civicrm/CRM/Activity/DAO/Activity.php +++ b/civicrm/CRM/Activity/DAO/Activity.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Activity/Activity.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:0dd661946f59d928e2b928c3c3f67d44) + * (GenCodeChecksum:e29dddab1cbaae042d11ea6e022f3dd5) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -309,7 +309,7 @@ class CRM_Activity_DAO_Activity extends CRM_Core_DAO { 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'activity_duration' => array( diff --git a/civicrm/CRM/Activity/Form/Task/Batch.php b/civicrm/CRM/Activity/Form/Task/Batch.php index 5e0598cb96abc728963f51a711079c713143d4dd..980ef2c808aa8529b52717941ffada57255c28c4 100644 --- a/civicrm/CRM/Activity/Form/Task/Batch.php +++ b/civicrm/CRM/Activity/Form/Task/Batch.php @@ -78,8 +78,8 @@ class CRM_Activity_Form_Task_Batch extends CRM_Activity_Form_Task { if (!empty($contactDetails)) { foreach ($contactDetails as $key => $value) { $assignee = CRM_Activity_BAO_ActivityAssignment::retrieveAssigneeIdsByActivityId($key); - foreach ($assignee as $keys => $values) { - $assigneeContact[] = CRM_Contact_BAO_Contact::displayname($values); + foreach ($assignee as $values) { + $assigneeContact[] = CRM_Contact_BAO_Contact::displayName($values); } $contactDetails[$key]['assignee_display_name'] = !empty($assigneeContact) ? implode(';', $assigneeContact) : NULL; } @@ -138,7 +138,6 @@ class CRM_Activity_Form_Task_Batch extends CRM_Activity_Form_Task { $this->assign('profileTitle', $this->_title); $this->assign('componentIds', $this->_activityHolderIds); - $fileFieldExists = FALSE; // Load all campaigns. if (array_key_exists('activity_campaign_id', $this->_fields)) { @@ -197,7 +196,6 @@ class CRM_Activity_Form_Task_Batch extends CRM_Activity_Form_Task { $defaults = array(); foreach ($this->_activityHolderIds as $activityId) { - $details[$activityId] = array(); CRM_Core_BAO_UFGroup::setProfileDefaults(NULL, $this->_fields, $defaults, FALSE, $activityId, 'Activity'); } diff --git a/civicrm/CRM/Admin/Form.php b/civicrm/CRM/Admin/Form.php index cc3186887fcc6cf3cce791421ca49978d3b14808..8129e3f18466135d86ae47c8b3df74a0c91b9f92 100644 --- a/civicrm/CRM/Admin/Form.php +++ b/civicrm/CRM/Admin/Form.php @@ -91,7 +91,7 @@ class CRM_Admin_Form extends CRM_Core_Form { */ public function setDefaultValues() { // Fetch defaults from the db - if (isset($this->_id) && empty($this->_values)) { + if (!empty($this->_id) && empty($this->_values) && CRM_Utils_Rule::positiveInteger($this->_id)) { $this->_values = array(); $params = array('id' => $this->_id); $baoName = $this->_BAOName; diff --git a/civicrm/CRM/Admin/Form/Setting.php b/civicrm/CRM/Admin/Form/Setting.php index 16df7ca1e2dcddc8c4ffff7dc62c25872e88d230..671c8fe7ed3fb7cccadaf4b84370871568c78e6f 100644 --- a/civicrm/CRM/Admin/Form/Setting.php +++ b/civicrm/CRM/Admin/Form/Setting.php @@ -203,16 +203,11 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form { unset($params['enableComponents']); } - // verify ssl peer option - if (isset($params['verifySSL'])) { - Civi::settings()->set('verifySSL', $params['verifySSL']); - unset($params['verifySSL']); - } - - // force secure URLs - if (isset($params['enableSSL'])) { - Civi::settings()->set('enableSSL', $params['enableSSL']); - unset($params['enableSSL']); + foreach (array('verifySSL', 'enableSSL') as $name) { + if (isset($params[$name])) { + Civi::settings()->set($name, $params[$name]); + unset($params[$name]); + } } $settings = array_intersect_key($params, $this->_settings); $result = civicrm_api('setting', 'create', $settings + array('version' => 3)); diff --git a/civicrm/CRM/Admin/Form/Setting/UF.php b/civicrm/CRM/Admin/Form/Setting/UF.php index 342d6f357ae4a24716fa40aaa22653d0397c4a50..ab290514d38b8b657ce64717c4c84e39c587e242 100644 --- a/civicrm/CRM/Admin/Form/Setting/UF.php +++ b/civicrm/CRM/Admin/Form/Setting/UF.php @@ -46,6 +46,7 @@ class CRM_Admin_Form_Setting_UF extends CRM_Admin_Form_Setting { public function buildQuickForm() { $config = CRM_Core_Config::singleton(); $this->_uf = $config->userFramework; + $this->_settings['syncCMSEmail'] = CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME; if ($this->_uf == 'WordPress') { $this->_settings['wpBasePage'] = CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME; diff --git a/civicrm/CRM/Admin/Page/AJAX.php b/civicrm/CRM/Admin/Page/AJAX.php index 5740851eaa28ade287e360a12b5305d75f499d02..ebf77802a8f6553f2b634ae3e922b344f24f0516 100644 --- a/civicrm/CRM/Admin/Page/AJAX.php +++ b/civicrm/CRM/Admin/Page/AJAX.php @@ -247,55 +247,6 @@ class CRM_Admin_Page_AJAX { CRM_Core_Page_AJAX::returnJsonResponse($ret); } - public static function mergeTagList() { - $name = CRM_Utils_Type::escape($_GET['term'], 'String'); - $fromId = CRM_Utils_Type::escape($_GET['fromId'], 'Integer'); - $limit = Civi::settings()->get('search_autocomplete_count'); - - // build used-for clause to be used in main query - $usedForTagA = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $fromId, 'used_for'); - $usedForClause = array(); - if ($usedForTagA) { - $usedForTagA = explode(",", $usedForTagA); - foreach ($usedForTagA as $key => $value) { - $usedForClause[] = "t1.used_for LIKE '%{$value}%'"; - } - } - $usedForClause = !empty($usedForClause) ? implode(' OR ', $usedForClause) : '1'; - sort($usedForTagA); - - // query to list mergable tags - $query = " -SELECT t1.name, t1.id, t1.used_for, t1.color, t2.name as parent -FROM civicrm_tag t1 -LEFT JOIN civicrm_tag t2 ON t1.parent_id = t2.id -WHERE t1.id <> {$fromId} AND - t1.name LIKE '%{$name}%' AND - ({$usedForClause}) -LIMIT $limit"; - $dao = CRM_Core_DAO::executeQuery($query); - $result = array(); - - while ($dao->fetch()) { - $row = array( - 'id' => $dao->id, - 'text' => ($dao->parent ? "{$dao->parent} :: " : '') . $dao->name, - 'color' => isset($dao->color) ? $dao->color : NULL, - ); - // Add warning about used_for types - if (!empty($dao->used_for)) { - $usedForTagB = explode(',', $dao->used_for); - sort($usedForTagB); - $usedForDiff = array_diff($usedForTagA, $usedForTagB); - if (!empty($usedForDiff)) { - $row['warning'] = TRUE; - } - } - $result[] = $row; - } - CRM_Utils_JSON::output($result); - } - /** * Get a list of mappings. * @@ -352,24 +303,53 @@ LIMIT $limit"; )); } - public static function mergeTags() { - $tagAId = CRM_Utils_Type::escape($_POST['fromId'], 'Integer'); - $tagBId = CRM_Utils_Type::escape($_POST['toId'], 'Integer'); - - $result = CRM_Core_BAO_EntityTag::mergeTags($tagAId, $tagBId); + /** + * Outputs one branch in the tag tree + * + * Used by jstree to incrementally load tags + */ + public static function getTagTree() { + $parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer'); + $result = array(); - if (!empty($result['tagB_used_for'])) { - $usedFor = CRM_Core_OptionGroup::values('tag_used_for'); - foreach ($result['tagB_used_for'] as & $val) { - $val = $usedFor[$val]; + $parentClause = $parent ? "AND tag.parent_id = $parent" : 'AND tag.parent_id IS NULL'; + $sql = "SELECT tag.*, child.id AS child, COUNT(et.id) as usages + FROM civicrm_tag tag + LEFT JOIN civicrm_entity_tag et ON et.tag_id = tag.id + LEFT JOIN civicrm_tag child ON child.parent_id = tag.id + WHERE tag.is_tagset <> 1 $parentClause + GROUP BY tag.id + ORDER BY tag.name"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $style = ''; + if ($dao->color) { + $style = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color); } - $result['tagB_used_for'] = implode(', ', $result['tagB_used_for']); + $result[] = array( + 'id' => $dao->id, + 'text' => $dao->name, + 'icon' => FALSE, + 'li_attr' => array( + 'title' => ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : ''), + 'class' => $dao->is_reserved ? 'is-reserved' : '', + ), + 'a_attr' => array( + 'style' => $style, + 'class' => 'crm-tag-item', + ), + 'children' => (bool) $dao->child, + 'data' => array( + 'description' => (string) $dao->description, + 'is_selectable' => (bool) $dao->is_selectable, + 'is_reserved' => (bool) $dao->is_reserved, + 'used_for' => $dao->used_for ? explode(',', $dao->used_for) : array(), + 'color' => $dao->color ? $dao->color : '#ffffff', + 'usages' => (int) $dao->usages, + ), + ); } - $result['message'] = ts('"%1" has been merged with "%2". All records previously tagged "%1" are now tagged "%2".', - array(1 => $result['tagA'], 2 => $result['tagB']) - ); - CRM_Utils_JSON::output($result); } diff --git a/civicrm/CRM/Batch/Form/Entry.php b/civicrm/CRM/Batch/Form/Entry.php index dd61256132df7041de1b6823cad11d4b318decc6..60e967723ddb5b7caa45597acd3e1f25454fcbfc 100644 --- a/civicrm/CRM/Batch/Form/Entry.php +++ b/civicrm/CRM/Batch/Form/Entry.php @@ -382,9 +382,7 @@ class CRM_Batch_Form_Entry extends CRM_Core_Form { if ($this->_action & CRM_Core_Action::ADD) { list($currentDate, $currentTime) = CRM_Utils_Date::setDateDefaults(NULL, 'activityDateTime'); - //get all status - $allStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); - $completeStatus = array_search('Completed', $allStatus); + $completeStatus = CRM_Contribute_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'); $specialFields = array( 'join_date' => $currentDate, 'receive_date' => $currentDate, diff --git a/civicrm/CRM/Contact/BAO/Contact/Permission.php b/civicrm/CRM/Contact/BAO/Contact/Permission.php index 3948de9dd8b9625f67096a6133370fad596f93eb..a37e40e7f8bc9a200a2c2c5a08cf79f313560ad3 100644 --- a/civicrm/CRM/Contact/BAO/Contact/Permission.php +++ b/civicrm/CRM/Contact/BAO/Contact/Permission.php @@ -170,7 +170,7 @@ WHERE contact_id IN ({$contact_id_list}) $tables = array(); $whereTables = array(); - $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables); + $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, NULL, FALSE, FALSE, TRUE); $from = CRM_Contact_BAO_Query::fromClause($whereTables); $query = " diff --git a/civicrm/CRM/Contact/BAO/Group.php b/civicrm/CRM/Contact/BAO/Group.php index fe781a5cc35baf0442c8b73bb6f51b93e38f9ddd..aab9bc9cd9f7d7102b4d1385c8826d6ed3a8bd7e 100644 --- a/civicrm/CRM/Contact/BAO/Group.php +++ b/civicrm/CRM/Contact/BAO/Group.php @@ -900,7 +900,7 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group { $visibility = CRM_Core_SelectValues::ufVisibility(); while ($object->fetch()) { - $permission = CRM_Contact_BAO_Group::checkPermission($object->id, $object->title); + $permission = CRM_Contact_BAO_Group::checkPermission($object->id, TRUE); //@todo CRM-12209 introduced an ACL check in the whereClause function // it may be that this checking is now obsolete - or that what remains // should be removed to the whereClause (which is also accessed by getCount) diff --git a/civicrm/CRM/Contact/BAO/GroupContact.php b/civicrm/CRM/Contact/BAO/GroupContact.php index e50f028ad3ceb0a4afd5fc9e23ae3f2f2a13733c..8833d1958d48ac7b0aabbf273c58a22425895fa8 100644 --- a/civicrm/CRM/Contact/BAO/GroupContact.php +++ b/civicrm/CRM/Contact/BAO/GroupContact.php @@ -134,6 +134,9 @@ class CRM_Contact_BAO_GroupContact extends CRM_Contact_DAO_GroupContact { $status = 'Added', $tracking = NULL ) { + if (empty($contactIds) || empty($groupId)) { + return array(); + } CRM_Utils_Hook::pre('create', 'GroupContact', $groupId, $contactIds); diff --git a/civicrm/CRM/Contact/BAO/Query.php b/civicrm/CRM/Contact/BAO/Query.php index f0bda01fa8fba8737079693764539d35d72269e2..e905154411da95ee7a2536cae69c1376c84cb407 100644 --- a/civicrm/CRM/Contact/BAO/Query.php +++ b/civicrm/CRM/Contact/BAO/Query.php @@ -654,8 +654,6 @@ class CRM_Contact_BAO_Query { (substr($name, 0, 12) == 'participant_') || (substr($name, 0, 7) == 'pledge_') || (substr($name, 0, 5) == 'case_') || - (substr($name, 0, 13) == 'contribution_' && - (strpos($name, 'source') !== FALSE && strpos($name, 'recur') !== FALSE)) || (substr($name, 0, 8) == 'payment_') ) { continue; @@ -700,15 +698,12 @@ class CRM_Contact_BAO_Query { } } - if (in_array($name, array('prefix_id', 'suffix_id', 'gender_id', 'communication_style_id'))) { - if (CRM_Utils_Array::value($field['pseudoconstant']['optionGroupName'], $this->_returnProperties)) { - $makeException = TRUE; - } - } - $cfID = CRM_Core_BAO_CustomField::getKeyID($name); - if (!empty($this->_paramLookup[$name]) || !empty($this->_returnProperties[$name]) || - $makeException + if ( + !empty($this->_paramLookup[$name]) + || !empty($this->_returnProperties[$name]) + || $this->pseudoConstantNameIsInReturnProperties($field) + || $makeException ) { if ($cfID) { // add to cfIDs array if not present @@ -828,42 +823,12 @@ class CRM_Contact_BAO_Query { $this->_element['provider_id'] = 1; } - if ($tName == 'contact') { + if ($tName == 'contact' && $fieldName == 'organization_name') { // special case, when current employer is set for Individual contact - if ($fieldName == 'organization_name') { - $this->_select[$name] = "IF ( contact_a.contact_type = 'Individual', NULL, contact_a.organization_name ) as organization_name"; - } - elseif ($fieldName != 'id') { - if ($fieldName == 'prefix_id') { - $this->_pseudoConstantsSelect['individual_prefix'] = array( - 'pseudoField' => 'prefix_id', - 'idCol' => "prefix_id", - 'bao' => 'CRM_Contact_BAO_Contact', - ); - } - if ($fieldName == 'suffix_id') { - $this->_pseudoConstantsSelect['individual_suffix'] = array( - 'pseudoField' => 'suffix_id', - 'idCol' => "suffix_id", - 'bao' => 'CRM_Contact_BAO_Contact', - ); - } - if ($fieldName == 'gender_id') { - $this->_pseudoConstantsSelect['gender'] = array( - 'pseudoField' => 'gender_id', - 'idCol' => "gender_id", - 'bao' => 'CRM_Contact_BAO_Contact', - ); - } - if ($name == 'communication_style_id') { - $this->_pseudoConstantsSelect['communication_style'] = array( - 'pseudoField' => 'communication_style_id', - 'idCol' => "communication_style_id", - 'bao' => 'CRM_Contact_BAO_Contact', - ); - } - $this->_select[$name] = "contact_a.{$fieldName} as `$name`"; - } + $this->_select[$name] = "IF ( contact_a.contact_type = 'Individual', NULL, contact_a.organization_name ) as organization_name"; + } + elseif ($tName == 'contact' && $fieldName === 'id') { + // Handled elsewhere, explicitly ignore. Possibly for all tables... } elseif (in_array($tName, array('country', 'county'))) { $this->_pseudoConstantsSelect[$name]['select'] = "{$field['where']} as `$name`"; @@ -879,7 +844,22 @@ class CRM_Contact_BAO_Query { } } else { - $this->_select[$name] = "{$field['where']} as `$name`"; + // If we have an option group defined then rather than joining the option value table in + // (which is an unindexed join) we render the option value on output. + // @todo - extend this to other pseudoconstants. + if ($this->pseudoConstantNameIsInReturnProperties($field)) { + $pseudoFieldName = $field['pseudoconstant']['optionGroupName']; + $this->_pseudoConstantsSelect[$pseudoFieldName] = array( + 'pseudoField' => $field['name'], + 'idCol' => $field['name'], + 'field_name' => $field['name'], + 'bao' => $field['bao'], + 'pseudoconstant' => $field['pseudoconstant'], + ); + $this->_tables[$tableName] = 1; + $this->_element[$pseudoFieldName] = 1; + } + $this->_select[$name] = str_replace('civicrm_contact.', 'contact_a.', "{$field['where']} as `$name`"); } if (!in_array($tName, array('state_province', 'country', 'county'))) { $this->_element[$name] = 1; @@ -2968,7 +2948,6 @@ class CRM_Contact_BAO_Query { else { $statii[] = "'Added'"; } - $groupClause = array(); if (count($regularGroupIDs) || empty($value)) { $groupIds = implode(',', (array) $regularGroupIDs); @@ -4340,7 +4319,7 @@ civicrm_relationship.is_permission_a_b = 0 $smartGroupCache = TRUE, $count = FALSE, $skipPermissions = TRUE, - $mode = 1, + $mode = CRM_Contact_BAO_Query::MODE_CONTACTS, $apiEntity = NULL ) { @@ -4403,7 +4382,7 @@ civicrm_relationship.is_permission_a_b = 0 return array($noRows, NULL); } $val = $query->store($dao); - $convertedVals = $query->convertToPseudoNames($dao, TRUE); + $convertedVals = $query->convertToPseudoNames($dao, TRUE, TRUE); if (!empty($convertedVals)) { $val = array_replace_recursive($val, $convertedVals); @@ -5832,12 +5811,40 @@ AND displayRelType.is_active = 1 $val = $dao->{$value['idCol']}; if ($key == 'groups') { $dao->groups = $this->convertGroupIDStringToLabelString($dao, $val); - return; + continue; } if (CRM_Utils_System::isNull($val)) { $dao->$key = NULL; } + elseif (!empty($value['pseudoconstant'])) { + // If pseudoconstant is set that is kind of defacto for 'we have a bit more info about this' + // and we can use the metadata to figure it out. + // ideally this bit of IF will absorb & replace all the rest in time as we move to + // more metadata based choices. + if (strpos($val, CRM_Core_DAO::VALUE_SEPARATOR) !== FALSE) { + $dbValues = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($val, CRM_Core_DAO::VALUE_SEPARATOR)); + foreach ($dbValues as $pseudoValue) { + $convertedValues[] = CRM_Core_PseudoConstant::getLabel($value['bao'], $value['idCol'], $pseudoValue); + } + + $dao->$key = ($usedForAPI) ? $convertedValues : implode(', ', $convertedValues); + $realFieldName = CRM_Utils_Array::value('field_name', $this->_pseudoConstantsSelect[$key]); + if ($usedForAPI && $realFieldName) { + // normally we would see 2 fields returned for pseudoConstants. An exception is + // preferred_communication_method where there is no id-variant. + // For the api we prioritise getting the real data returned. + // over the resolved version + $dao->$realFieldName = $dbValues; + } + + } + else { + // This is basically the same as the default but since we have the bao we can use + // a cached function. + $dao->$key = CRM_Core_PseudoConstant::getLabel($value['bao'], $value['idCol'], $val); + } + } elseif ($baoName = CRM_Utils_Array::value('bao', $value, NULL)) { //preserve id value $idColumn = "{$key}_id"; @@ -5853,8 +5860,7 @@ AND displayRelType.is_active = 1 elseif ($value['pseudoField'] == 'state_province_abbreviation') { $dao->$key = CRM_Core_PseudoConstant::stateProvinceAbbreviation($val); } - // FIX ME: we should potentially move this to component Query and write a wrapper function that - // handles pseudoconstant fixes for all component + // @todo handle this in the section above for pseudoconstants. elseif (in_array($value['pseudoField'], array('participant_role_id', 'participant_role'))) { // @todo define bao on this & merge into the above condition. $viewValues = explode(CRM_Core_DAO::VALUE_SEPARATOR, $val); @@ -5892,6 +5898,21 @@ AND displayRelType.is_active = 1 } } } + if (!$usedForAPI) { + foreach (array( + 'gender_id' => 'gender', + 'prefix_id' => 'individual_prefix', + 'suffix_id' => 'individual_suffix', + 'communication_style_id' => 'communication_style', + ) as $realField => $labelField) { + // This is a temporary routine for handling these fields while + // we figure out how to handled them based on metadata in + /// export and search builder. CRM-19815, CRM-19830. + if (isset($dao->$realField) && is_numeric($dao->$realField) && isset($dao->$labelField)) { + $dao->$realField = $dao->$labelField; + } + } + } return $values; } @@ -6132,6 +6153,7 @@ AND displayRelType.is_active = 1 */ protected function prepareOrderBy($sort, $sortByChar, $sortOrder, $additionalFromClause) { $order = NULL; + $orderByArray = array(); $config = CRM_Core_Config::singleton(); if ($config->includeOrderByClause || isset($this->_distinctComponentClause) @@ -6168,60 +6190,62 @@ AND displayRelType.is_active = 1 } } elseif ($sortByChar) { - $order = " ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc"; + $orderByArray = array("UPPER(LEFT(contact_a.sort_name, 1)) asc"); } else { $order = " ORDER BY contact_a.sort_name asc, contact_a.id"; } } + if (!$order && empty($orderByArray)) { + return array($order, $additionalFromClause); + } + // Remove this here & add it at the end for simplicity. + $order = trim(str_replace('ORDER BY', '', $order)); // hack for order clause - if ($order) { - $fieldStr = trim(str_replace('ORDER BY', '', $order)); - $fieldOrder = explode(' ', $fieldStr); - $field = $fieldOrder[0]; - - if ($field) { - switch ($field) { - case 'city': - case 'postal_code': - $this->_tables["civicrm_address"] = $this->_whereTables["civicrm_address"] = 1; - $order = str_replace($field, "civicrm_address.{$field}", $order); - break; - - case 'country': - case 'state_province': - $this->_tables["civicrm_{$field}"] = $this->_whereTables["civicrm_{$field}"] = 1; - if (is_array($this->_returnProperties) && empty($this->_returnProperties)) { - $additionalFromClause .= " LEFT JOIN civicrm_{$field} ON civicrm_{$field}.id = civicrm_address.{$field}_id"; - } - $order = str_replace($field, "civicrm_{$field}.name", $order); - break; + $fieldOrder = explode(' ', $order); + $field = $fieldOrder[0]; + + if ($field) { + switch ($field) { + case 'city': + case 'postal_code': + $this->_tables["civicrm_address"] = $this->_whereTables["civicrm_address"] = 1; + $order = str_replace($field, "civicrm_address.{$field}", $order); + break; + + case 'country': + case 'state_province': + $this->_tables["civicrm_{$field}"] = $this->_whereTables["civicrm_{$field}"] = 1; + if (is_array($this->_returnProperties) && empty($this->_returnProperties)) { + $additionalFromClause .= " LEFT JOIN civicrm_{$field} ON civicrm_{$field}.id = civicrm_address.{$field}_id"; + } + $order = str_replace($field, "civicrm_{$field}.name", $order); + break; - case 'email': - $this->_tables["civicrm_email"] = $this->_whereTables["civicrm_email"] = 1; - $order = str_replace($field, "civicrm_email.{$field}", $order); - break; + case 'email': + $this->_tables["civicrm_email"] = $this->_whereTables["civicrm_email"] = 1; + $order = str_replace($field, "civicrm_email.{$field}", $order); + break; - default: - //CRM-12565 add "`" around $field if it is a pseudo constant - foreach ($this->_pseudoConstantsSelect as $key => $value) { - if (!empty($value['element']) && $value['element'] == $field) { - $order = str_replace($field, "`{$field}`", $order); - } + default: + //CRM-12565 add "`" around $field if it is a pseudo constant + foreach ($this->_pseudoConstantsSelect as $key => $value) { + if (!empty($value['element']) && $value['element'] == $field) { + $order = str_replace($field, "`{$field}`", $order); } - } - $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode); - $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); + } } + $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode); + $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); } // The above code relies on crazy brittle string manipulation of a peculiarly-encoded ORDER BY // clause. But this magic helper which forgivingly reescapes ORDER BY. // Note: $sortByChar implies that $order was hard-coded/trusted, so it can do funky things. if ($order && !$sortByChar) { - $order = ' ORDER BY ' . CRM_Utils_Type::escape(preg_replace('/^\s*ORDER BY\s*/', '', $order), 'MysqlOrderBy'); - return array($order, $additionalFromClause); + $order = CRM_Utils_Type::escape($order, 'MysqlOrderBy'); + return array(' ORDER BY ' . $order, $additionalFromClause); } return array($order, $additionalFromClause); } @@ -6273,4 +6297,33 @@ AND displayRelType.is_active = 1 )); } + /** + * Has the pseudoconstant of the field been requested. + * + * For example if the field is payment_instrument_id then it + * has been requested if either payment_instrument_id or payment_instrument + * have been requested. Payment_instrument is the option groun name field value. + * + * @param array $field + * + * @return bool + */ + private function pseudoConstantNameIsInReturnProperties($field) { + if (!isset($field['pseudoconstant']['optionGroupName'])) { + return FALSE; + } + if (empty($field['bao']) || $field['bao'] != 'CRM_Contact_BAO_Contact') { + // For now.... + return FALSE; + } + + if (CRM_Utils_Array::value($field['pseudoconstant']['optionGroupName'], $this->_returnProperties)) { + return TRUE; + } + if (CRM_Utils_Array::value($field['name'], $this->_returnProperties)) { + return TRUE; + } + return FALSE; + } + } diff --git a/civicrm/CRM/Contact/DAO/Contact.php b/civicrm/CRM/Contact/DAO/Contact.php index dd66d1e92464143ffc6b9a6c67cdef8a57f44b92..0f375714fc7d0bb112e78e28912cac960958530a 100644 --- a/civicrm/CRM/Contact/DAO/Contact.php +++ b/civicrm/CRM/Contact/DAO/Contact.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Contact/Contact.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:0c8e687501dbd8f44354ee5f5cdf9b52) + * (GenCodeChecksum:b16421c318c1224c65e18a9e2aa15a5e) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -1114,7 +1114,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO { 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select Date', - 'format' => 'birth', + 'formatType' => 'birth', ) , ) , 'is_deceased' => array( @@ -1148,7 +1148,7 @@ class CRM_Contact_DAO_Contact extends CRM_Core_DAO { 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select Date', - 'format' => 'birth', + 'formatType' => 'birth', ) , ) , 'household_name' => array( diff --git a/civicrm/CRM/Contact/Form/Merge.php b/civicrm/CRM/Contact/Form/Merge.php index ad9a8e6563dc512b23e59401e7a859769f30d862..9445834f0a7cb638c5e67d63c613e2b71ca9f69b 100644 --- a/civicrm/CRM/Contact/Form/Merge.php +++ b/civicrm/CRM/Contact/Form/Merge.php @@ -78,24 +78,25 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { $this->limit = CRM_Utils_Request::retrieve('limit', 'Positive', $this, FALSE); $urlParams = "reset=1&rgid={$this->_rgid}&gid={$this->_gid}&limit=" . $this->limit; - // Sanity check - if ($cid == $oid) { - CRM_Core_Error::statusBounce(ts('Cannot merge a contact with itself.')); - } + $this->bounceIfInvalid($cid, $oid); - if (!CRM_Dedupe_BAO_Rule::validateContacts($cid, $oid)) { - CRM_Core_Error::statusBounce(ts('The selected pair of contacts are marked as non duplicates. If these records should be merged, you can remove this exception on the <a href="%1">Dedupe Exceptions</a> page.', array(1 => CRM_Utils_System::url('civicrm/dedupe/exception', 'reset=1')))); - } $this->_contactType = civicrm_api3('Contact', 'getvalue', array('id' => $cid, 'return' => 'contact_type')); - $isFromDedupeScreen = TRUE; + + $browseUrl = CRM_Utils_System::url('civicrm/contact/dedupefind', $urlParams . '&action=browse'); + if (!$this->_rgid) { - $isFromDedupeScreen = FALSE; + // Unset browse URL as we have come from the search screen. + $browseUrl = ''; $this->_rgid = civicrm_api3('RuleGroup', 'getvalue', array( 'contact_type' => $this->_contactType, 'used' => 'Supervised', 'return' => 'id', )); } + $this->assign('browseUrl', $browseUrl); + if ($browseUrl) { + CRM_Core_Session::singleton()->pushUserContext($browseUrl); + } $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid); @@ -104,14 +105,6 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { $pos = CRM_Core_BAO_PrevNextCache::getPositions($cacheKey, $cid, $oid, $this->_mergeId, $join, $where, $flip); - // Block access if user does not have EDIT permissions for both contacts. - if (!(CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT) && - CRM_Contact_BAO_Contact_Permission::allow($oid, CRM_Core_Permission::EDIT) - ) - ) { - CRM_Utils_System::permissionDenied(); - } - // get user info of main contact. $config = CRM_Core_Config::singleton(); $config->doNotResetCache = 1; @@ -176,25 +169,9 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { $session = CRM_Core_Session::singleton(); - // context fixed. - if ($isFromDedupeScreen) { - $browseUrl = CRM_Utils_System::url('civicrm/contact/dedupefind', $urlParams . '&action=browse'); - $session->pushUserContext($browseUrl); - } - $this->assign('browseUrl', empty($browseUrl) ? '' : $browseUrl); - - // ensure that oid is not the current user, if so refuse to do the merge - if ($session->get('userID') == $oid) { - $display_name = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $oid, 'display_name'); - $message = ts('The contact record which is linked to the currently logged in user account - \'%1\' - cannot be deleted.', - array(1 => $display_name) - ); - CRM_Core_Error::statusBounce($message); - } - $rowsElementsAndInfo = CRM_Dedupe_Merger::getRowsElementsAndInfo($cid, $oid); - $main = $this->_mainDetails = &$rowsElementsAndInfo['main_details']; - $other = $this->_otherDetails = &$rowsElementsAndInfo['other_details']; + $main = $this->_mainDetails = $rowsElementsAndInfo['main_details']; + $other = $this->_otherDetails = $rowsElementsAndInfo['other_details']; if ($main['contact_id'] != $cid) { CRM_Core_Error::fatal(ts('The main contact record does not exist')); @@ -222,6 +199,19 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { // add elements foreach ($rowsElementsAndInfo['elements'] as $element) { + // We could push this down to the getRowsElementsAndInfo function but it's + // already so overloaded - let's start moving towards doing form-things + // on the form. + if (substr($element[1], 0, 13) === 'move_location') { + $element[4] = array_merge( + (array) CRM_Utils_Array::value(4, $element, array()), + array('data-location' => substr($element[1], 14), 'data-is_location' => TRUE)); + } + if (substr($element[1], 0, 15) === 'location_blocks') { + // @todo We could add some data elements here to make jquery manipulation more straight-forward + // @todo consider enabling if it is an add & defaulting to true. + $element[4] = array_merge((array) CRM_Utils_Array::value(4, $element, array()), array('disabled' => TRUE)); + } $this->addElement($element[0], $element[1], array_key_exists('2', $element) ? $element[2] : NULL, @@ -241,22 +231,6 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { $this->assign('userContextURL', $session->readUserContext()); } - /** - * This virtual function is used to set the default values of - * various form elements - * - * access public - * - * @return array - * reference to the array of default values - */ - /** - * @return array - */ - public function setDefaultValues() { - return array('deleteOther' => 1); - } - public function addRules() { } @@ -366,4 +340,39 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form { CRM_Utils_System::redirect($url); } + /** + * Bounce if the merge action is invalid. + * + * We don't allow the merge if it is nonsensical, marked as a duplicate + * or outside the user's permission. + * + * @param int $cid + * Contact ID to retain + * @param int $oid + * Contact ID to delete. + */ + public function bounceIfInvalid($cid, $oid) { + if ($cid == $oid) { + CRM_Core_Error::statusBounce(ts('Cannot merge a contact with itself.')); + } + + if (!CRM_Dedupe_BAO_Rule::validateContacts($cid, $oid)) { + CRM_Core_Error::statusBounce(ts('The selected pair of contacts are marked as non duplicates. If these records should be merged, you can remove this exception on the <a href="%1">Dedupe Exceptions</a> page.', array(1 => CRM_Utils_System::url('civicrm/dedupe/exception', 'reset=1')))); + } + + if (!(CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT) && + CRM_Contact_BAO_Contact_Permission::allow($oid, CRM_Core_Permission::EDIT) + ) + ) { + CRM_Utils_System::permissionDenied(); + } + // ensure that oid is not the current user, if so refuse to do the merge + if (CRM_Core_Session::singleton()->getLoggedInContactID() == $oid) { + $message = ts('The contact record which is linked to the currently logged in user account - \'%1\' - cannot be deleted.', + array(1 => CRM_Core_Session::singleton()->getLoggedInContactDisplayName()) + ); + CRM_Core_Error::statusBounce($message); + } + } + } diff --git a/civicrm/CRM/Contact/Page/DedupeFind.php b/civicrm/CRM/Contact/Page/DedupeFind.php index aaaebefe4bca38f3d7b280e657ba2112ff8858ee..affce8e20d297a38ad6df425214988111da7c2cb 100644 --- a/civicrm/CRM/Contact/Page/DedupeFind.php +++ b/civicrm/CRM/Contact/Page/DedupeFind.php @@ -88,7 +88,7 @@ class CRM_Contact_Page_DedupeFind extends CRM_Core_Page_Basic { } elseif ($action & CRM_Core_Action::MAP) { // do a batch merge if requested - $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', TRUE, 75); + $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', 75); $skippedCount = CRM_Utils_Request::retrieve('skipped', 'Positive', $this, FALSE, 0); $skippedCount = $skippedCount + count($result['skipped']); diff --git a/civicrm/CRM/Contact/Page/DedupeMerge.php b/civicrm/CRM/Contact/Page/DedupeMerge.php index ffcd028def6f1965c13bcc382c796fca1d5566fa..df91a146f4a8596ebc605ef44545ea5192e27efe 100644 --- a/civicrm/CRM/Contact/Page/DedupeMerge.php +++ b/civicrm/CRM/Contact/Page/DedupeMerge.php @@ -98,7 +98,7 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page { for ($i = 1; $i <= ceil($total / self::BATCHLIMIT); $i++) { $task = new CRM_Queue_Task( array('CRM_Contact_Page_DedupeMerge', 'callBatchMerge'), - array($rgid, $gid, $mode, FALSE, self::BATCHLIMIT, $isSelected), + array($rgid, $gid, $mode, self::BATCHLIMIT, $isSelected), "Processed " . $i * self::BATCHLIMIT . " pair of duplicates out of " . $total ); @@ -126,17 +126,13 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page { * @param int $gid * @param string $mode * 'safe' mode or 'force' mode. - * @param bool $autoFlip - * Override the values in the prevnext table & use the lowest value? - * As the form offers the user to flip the values themselves this should - * only be TRUE if you wish to ignore the user. * @param int $batchLimit * @param int $isSelected * * @return int */ - public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $autoFlip, $batchLimit, $isSelected) { - CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $autoFlip, $batchLimit, $isSelected); + public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $batchLimit, $isSelected) { + CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $batchLimit, $isSelected); return CRM_Queue_Task::TASK_SUCCESS; } diff --git a/civicrm/CRM/Contact/Page/SavedSearch.php b/civicrm/CRM/Contact/Page/SavedSearch.php index 950531d28b6da9fb428133d4fe84c6b5ce56ef6e..ab9f39bd2deef84913ed2d05c3df51d9b3693006 100644 --- a/civicrm/CRM/Contact/Page/SavedSearch.php +++ b/civicrm/CRM/Contact/Page/SavedSearch.php @@ -83,7 +83,7 @@ class CRM_Contact_Page_SavedSearch extends CRM_Core_Page { $group = new CRM_Contact_DAO_Group(); $group->saved_search_id = $savedSearch->id; if ($group->find(TRUE)) { - $permissions = CRM_Group_Page_Group::checkPermission($group->id, $group->title); + $permissions = CRM_Contact_BAO_Group::checkPermission($group->id, TRUE); if (!CRM_Utils_System::isNull($permissions)) { $row = array(); diff --git a/civicrm/CRM/Contact/Selector.php b/civicrm/CRM/Contact/Selector.php index 8a92ce1a099b364d3e862771bb3d6bfb7c629894..8cb3ec84e6cb56fb8bf4b74db129fa8808083a37 100644 --- a/civicrm/CRM/Contact/Selector.php +++ b/civicrm/CRM/Contact/Selector.php @@ -637,8 +637,6 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se $names = self::$_properties; } - $multipleSelectFields = array('preferred_communication_method' => 1); - $links = self::links($this->_context, $this->_contextMenu, $this->_key); //check explicitly added contact to a Smart Group. @@ -656,7 +654,6 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se while ($result->fetch()) { $row = array(); $this->_query->convertToPseudoNames($result); - // the columns we are interested in foreach ($names as $property) { if ($property == 'status') { @@ -669,17 +666,6 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se $result->contact_id ); } - elseif ( - $multipleSelectFields && - array_key_exists($property, $multipleSelectFields) - ) { - $key = $property; - $paramsNew = array($key => $result->$property); - $name = array($key => array('newName' => $key, 'groupName' => $key)); - - CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE); - $row[$key] = $paramsNew[$key]; - } elseif (strpos($property, '-im')) { $row[$property] = $result->$property; if (!empty($result->$property)) { diff --git a/civicrm/CRM/Contribute/BAO/Contribution.php b/civicrm/CRM/Contribute/BAO/Contribution.php index e74a29f2f0c2a6555f304905d375c51e1a0c99e6..ab6c479f012d08cb0294e0a4b8106718a0fc2830 100644 --- a/civicrm/CRM/Contribute/BAO/Contribution.php +++ b/civicrm/CRM/Contribute/BAO/Contribution.php @@ -825,15 +825,6 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { ), ); - $contributionRecurId = array( - 'contribution_recur_id' => array( - 'title' => ts('Recurring Contributions ID'), - 'name' => 'contribution_recur_id', - 'where' => 'civicrm_contribution.contribution_recur_id', - 'data_type' => CRM_Utils_Type::T_INT, - ), - ); - $extraFields = array( 'contribution_batch' => array( 'title' => ts('Batch Name'), @@ -893,7 +884,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { ); $fields = array_merge($impFields, $typeField, $contributionStatus, $contributionPage, $optionField, $expFieldProduct, - $expFieldsContrib, $contributionNote, $contributionRecurId, $extraFields, $softCreditFields, $financialAccount, $premiums, $campaignTitle, + $expFieldsContrib, $contributionNote, $extraFields, $softCreditFields, $financialAccount, $premiums, $campaignTitle, CRM_Core_BAO_CustomField::getFieldsForImport('Contribution', FALSE, FALSE, FALSE, $checkPermission) ); @@ -4476,6 +4467,12 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']}) )); $contributionParams['payment_processor'] = $input['payment_processor'] = $paymentProcessorId; + // If paymentProcessor is not set then the payment_instrument_id would not be correct. + // not clear when or if this would occur if you encounter this please fix here & add a unit test. + if (empty($contributionParams['payment_instrument_id']) && isset($contribution->_relatedObjects['paymentProcessor']['payment_instrument_id'])) { + $contributionParams['payment_instrument_id'] = $contribution->_relatedObjects['paymentProcessor']['payment_instrument_id']; + } + if ($recurringContributionID) { $contributionParams['contribution_recur_id'] = $recurringContributionID; } @@ -4718,14 +4715,8 @@ LIMIT 1;"; $contribution->loadRelatedObjects($input, $ids, TRUE); // set receipt from e-mail and name in value if (!$returnMessageText) { - $userID = CRM_Core_Session::singleton()->getLoggedInContactID(); - if (!empty($userID)) { - list($userName, $userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID); - $values['receipt_from_email'] = CRM_Utils_Array::value('receipt_from_email', $input, $userEmail); - $values['receipt_from_name'] = CRM_Utils_Array::value('receipt_from_name', $input, $userName); - } + list($values['receipt_from_name'], $values['receipt_from_email']) = self::generateFromEmailAndName($input, $contribution); } - $return = $contribution->composeMessageArray($input, $ids, $values, $recur, $returnMessageText); // Contribution ID should really always be set. But ? if (!$returnMessageText && (!isset($input['receipt_update']) || $input['receipt_update']) && empty($contribution->receipt_date)) { @@ -4734,6 +4725,42 @@ LIMIT 1;"; return $return; } + /** + * Generate From email and from name in an array values + */ + public static function generateFromEmailAndName($input, $contribution) { + // Use input valuse if supplied. + if (!empty($input['receipt_from_email'])) { + return array(CRM_Utils_array::value('receipt_from_name', $input, ''), $input['receipt_from_email']); + } + // if we are still empty see if we can use anything from a contribution page. + $pageValues = array(); + if (!empty($contribution->contribution_page_id)) { + $pageValues = civicrm_api3('ContributionPage', 'getsingle', array('id' => $contribution->contribution_page_id)); + } + // if we are still empty see if we can use anything from a contribution page. + if (!empty($pageValues['receipt_from_email'])) { + return array($pageValues['receipt_from_name'], $pageValues['receipt_from_email']); + } + // If we are still empty fall back to the domain. + $domain = civicrm_api3('domain', 'getsingle', array('id' => CRM_Core_Config::domainID())); + if (!empty($domain['from_email'])) { + return array($domain['from_name'], $domain['from_email']); + } + if (!empty($domain['domain_email'])) { + return array($domain['name'], $domain['domain_email']); + } + $userID = CRM_Core_Session::singleton()->getLoggedInContactID(); + $userName = ''; + $userEmail = ''; + if (!empty($userID)) { + list($userName, $userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID); + } + // If still empty fall back to the logged in user details. + // return empty values no matter what. + return array($userName, $userEmail); + } + /** * Generate credit note id with next avaible number * @@ -5390,8 +5417,8 @@ LEFT JOIN civicrm_contribution on (civicrm_contribution.contact_id = civicrm_co */ public static function createProportionalEntry($entityParams, $eftParams) { $paid = $entityParams['line_item_amount'] * ($entityParams['trxn_total_amount'] / $entityParams['contribution_total_amount']); - // Record Entity Financial Trxn - $eftParams['amount'] = round($paid, 2); + // Record Entity Financial Trxn; CRM-20145 + $eftParams['amount'] = CRM_Contribute_BAO_Contribution_Utils::formatAmount($paid); civicrm_api3('EntityFinancialTrxn', 'create', $eftParams); } diff --git a/civicrm/CRM/Contribute/BAO/Contribution/Utils.php b/civicrm/CRM/Contribute/BAO/Contribution/Utils.php index 6ea7c5b271fdd09248d021d08cbe18f8a6619de2..6633d2fe43b64586a5c590091cfaf90111813280 100644 --- a/civicrm/CRM/Contribute/BAO/Contribution/Utils.php +++ b/civicrm/CRM/Contribute/BAO/Contribution/Utils.php @@ -475,9 +475,26 @@ LIMIT 1 */ public static function calculateTaxAmount($amount, $taxRate) { $taxAmount = array(); - $taxAmount['tax_amount'] = round(($taxRate / 100) * CRM_Utils_Rule::cleanMoney($amount), 2); + // There can not be any rounding at this stage - as this is prior to quantity multiplication + $taxAmount['tax_amount'] = ($taxRate / 100) * CRM_Utils_Rule::cleanMoney($amount); return $taxAmount; } + /** + * Format monetary amount: round and return to desired decimal place + * CRM-20145 + * + * @param float $amount + * Monetary amount + * @param int $decimals + * How many decimal places to round to and return + * + * @return float + * Amount rounded and returned with the desired decimal places + */ + public static function formatAmount($amount, $decimals = 2) { + return number_format((float) round($amount, (int) $decimals), (int) $decimals, '.', ''); + } + } diff --git a/civicrm/CRM/Contribute/BAO/Query.php b/civicrm/CRM/Contribute/BAO/Query.php index e09ddd64d1dfcf03f30f6b10a4092c279214b8f0..f7e4f5d06c8bde41517f1ce6407e1ef42139d490 100644 --- a/civicrm/CRM/Contribute/BAO/Query.php +++ b/civicrm/CRM/Contribute/BAO/Query.php @@ -97,12 +97,6 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { $query->_tables['contribution_batch'] = 1; } - if (!empty($query->_returnProperties['contribution_source'])) { - $query->_select['contribution_source'] = "civicrm_contribution.source as contribution_source"; - $query->_element['contribution_source'] = 1; - $query->_tables['civicrm_contribution'] = 1; - } - // get contribution_status if (!empty($query->_returnProperties['contribution_status_id'])) { $query->_select['contribution_status_id'] = "contribution_status.value as contribution_status_id"; @@ -136,39 +130,11 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { $query->_tables['contribution_payment_instrument'] = 1; } - if (!empty($query->_returnProperties['check_number'])) { - $query->_select['contribution_check_number'] = "civicrm_contribution.check_number as contribution_check_number"; - $query->_element['contribution_check_number'] = 1; - $query->_tables['civicrm_contribution'] = 1; - } - - if (!empty($query->_returnProperties['contribution_campaign_id'])) { - $query->_select['contribution_campaign_id'] = 'civicrm_contribution.campaign_id as contribution_campaign_id'; - $query->_element['contribution_campaign_id'] = 1; - $query->_tables['civicrm_contribution'] = 1; - } - if (!empty($query->_returnProperties['contribution_campaign_title'])) { $query->_select['contribution_campaign_title'] = "civicrm_campaign.title as contribution_campaign_title"; $query->_element['contribution_campaign_title'] = $query->_tables['civicrm_campaign'] = 1; } - // Adding address_id in a way that is more easily extendable since the above is a bit ... wordy. - $supportedBasicReturnValues = array('address_id'); - foreach ($supportedBasicReturnValues as $fieldName) { - if (!empty($query->_returnProperties[$fieldName]) && empty($query->_select[$fieldName])) { - $query->_select[$fieldName] = "civicrm_contribution.{$fieldName} as $fieldName"; - $query->_element[$fieldName] = $query->_tables['civicrm_contribution'] = 1; - } - } - - //CRM-16116: get financial_type_id - if (!empty($query->_returnProperties['financial_type_id'])) { - $query->_select['financial_type_id'] = "civicrm_contribution.financial_type_id as financial_type_id"; - $query->_element['financial_type_id'] = $query->_tables['civicrm_contribution'] = 1; - } - // LCD 716 END - self::addSoftCreditFields($query); } @@ -230,6 +196,20 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { return; } } + // These are legacy names. + // @todo enotices when these are hit so we can start to elimnate them. + $fieldAliases = array( + 'financial_type' => 'financial_type_id', + 'contribution_page' => 'contribution_page_id', + 'payment_instrument' => 'payment_instrument_id', + // or payment_instrument_id? + 'contribution_payment_instrument' => 'contribution_payment_instrument_id', + 'contribution_status' => 'contribution_status_id', + ); + $name = isset($fieldAliases[$name]) ? $fieldAliases[$name] : $name; + $qillName = $name; + $pseudoExtraParam = array(); + switch ($name) { case 'contribution_date': case 'contribution_date_low': @@ -279,12 +259,6 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { $query->_tables['civicrm_contribution'] = $query->_whereTables['civicrm_contribution'] = 1; return; - case 'financial_type': - case 'contribution_page': - case 'payment_instrument': - case 'contribution_payment_instrument': - case 'contribution_status': - $name .= '_id'; case 'financial_type_id': // @todo we need to make this resemble a hook approach. CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialTypes); @@ -304,26 +278,19 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { case (strpos($name, '_amount') !== FALSE): case (strpos($name, '_date') !== FALSE && $name != 'contribution_fulfilled_date'): case 'contribution_campaign_id': - $qillName = $name; - $pseudoExtraParam = array(); - // @todo including names using a switch statement & then using an 'if' to filter them out is ... odd! - if ((strpos($name, '_amount') !== FALSE) || (strpos($name, '_date') !== FALSE) || in_array($name, - array( - 'contribution_id', - 'contribution_currency', - 'contribution_source', - 'contribution_trxn_id', - 'contribution_check_number', - 'contribution_payment_instrument_id', - 'contribution_contact_id', - 'contribution_campaign_id', - ) - ) + + $fieldNamesNotToStripContributionFrom = array( + 'contribution_currency_type', + 'contribution_status_id', + 'contribution_page_id', + ); + // @todo these are mostly legacy params. Find a better way to deal with them. + if (!in_array($name, $fieldNamesNotToStripContributionFrom) ) { - $name = str_replace('contribution_', '', $name); - if (!in_array($name, array('source', 'id', 'contact_id', 'campaign_id'))) { + if (!isset($fields[$name])) { $qillName = str_replace('contribution_', '', $qillName); } + $name = str_replace('contribution_', '', $name); } if (in_array($name, array('contribution_currency', 'contribution_currency_type'))) { $qillName = $name = 'currency'; @@ -859,7 +826,7 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query { // kittens 'payment_instrument_id' => 1, // argh - 'check_number' => 1, + 'contribution_check_number' => 1, // no 'non_deductible_amount' => 1, // not diff --git a/civicrm/CRM/Contribute/DAO/Contribution.php b/civicrm/CRM/Contribute/DAO/Contribution.php index f35c3c7707717c2048b8a082d68a98fb3e807ea6..0a1a2f3eb3e2cd9689d773399020dce45bc7fa26 100644 --- a/civicrm/CRM/Contribute/DAO/Contribution.php +++ b/civicrm/CRM/Contribute/DAO/Contribution.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Contribute/Contribution.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:f066fa296dca6ef9876c7372a61c1a4a) + * (GenCodeChecksum:b25399b3b6cf17e97809102666de8ee7) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -291,7 +291,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Financial Type') , 'description' => 'FK to Financial Type for (total_amount - non_deductible_amount).', - 'export' => false, + 'export' => true, 'where' => 'civicrm_contribution.financial_type_id', 'headerPattern' => '', 'dataPattern' => '', @@ -362,7 +362,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'bao' => 'CRM_Contribute_BAO_Contribution', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'non_deductible_amount' => array( @@ -529,7 +529,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'bao' => 'CRM_Contribute_BAO_Contribution', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'cancel_reason' => array( @@ -563,7 +563,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'bao' => 'CRM_Contribute_BAO_Contribution', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'thankyou_date' => array( @@ -581,7 +581,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'bao' => 'CRM_Contribute_BAO_Contribution', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'contribution_source' => array( @@ -624,6 +624,10 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Recurring Contribution ID') , 'description' => 'Conditional foreign key to civicrm_contribution_recur id. Each contribution made in connection with a recurring contribution carries a foreign key to the recurring contribution record. This assumes we can track these processor initiated events.', + 'export' => true, + 'where' => 'civicrm_contribution.contribution_recur_id', + 'headerPattern' => '', + 'dataPattern' => '', 'table_name' => 'civicrm_contribution', 'entity' => 'Contribution', 'bao' => 'CRM_Contribute_BAO_Contribution', @@ -682,17 +686,21 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'optionEditPath' => 'civicrm/admin/options/contribution_status', ) ) , - 'address_id' => array( + 'contribution_address_id' => array( 'name' => 'address_id', 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Contribution Address') , 'description' => 'Conditional foreign key to civicrm_address.id. We insert an address record for each contribution when we have associated billing name and address data.', + 'export' => true, + 'where' => 'civicrm_contribution.address_id', + 'headerPattern' => '', + 'dataPattern' => '', 'table_name' => 'civicrm_contribution', 'entity' => 'Contribution', 'bao' => 'CRM_Contribute_BAO_Contribution', 'FKClassName' => 'CRM_Core_DAO_Address', ) , - 'check_number' => array( + 'contribution_check_number' => array( 'name' => 'check_number', 'type' => CRM_Utils_Type::T_STRING, 'title' => ts('Check Number') , @@ -788,7 +796,7 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO { 'bao' => 'CRM_Contribute_BAO_Contribution', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , ); diff --git a/civicrm/CRM/Contribute/Form/AdditionalPayment.php b/civicrm/CRM/Contribute/Form/AdditionalPayment.php index 993af0b77c73f0405af1259b6470faefa3befd92..b6cee86c1b75f7e8fd99350e96e6fa5fa8c2d788 100644 --- a/civicrm/CRM/Contribute/Form/AdditionalPayment.php +++ b/civicrm/CRM/Contribute/Form/AdditionalPayment.php @@ -429,15 +429,6 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract if (!empty($submittedValues['is_email_receipt']) && $sendReceipt) { $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.'); } - // email sending - if (!empty($result) && !empty($submittedValues['is_email_receipt'])) { - $submittedValues['contact_id'] = $this->_contactId; - $submittedValues['contribution_id'] = $this->_contributionId; - // to get 'from email id' for send receipt - $this->fromEmailId = $submittedValues['from_email_address']; - $sendReceipt = $this->emailReceipt($submittedValues); - } - CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success'); $session = CRM_Core_Session::singleton(); diff --git a/civicrm/CRM/Contribute/Form/Contribution.php b/civicrm/CRM/Contribute/Form/Contribution.php index 450c1bac94faf613e58387d697755c6272dd39a5..1f8b49c5136d8d46fa6f63347bed3a7bfabfec12 100644 --- a/civicrm/CRM/Contribute/Form/Contribution.php +++ b/civicrm/CRM/Contribute/Form/Contribution.php @@ -776,7 +776,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP if ($this->_online) { $this->assign('hideCalender', TRUE); } - $checkNumber = $this->add('text', 'check_number', ts('Check Number'), $attributes['check_number']); + $checkNumber = $this->add('text', 'check_number', ts('Check Number'), $attributes['contribution_check_number']); $this->addDateTime('receipt_date', ts('Receipt Date'), FALSE, array('formatType' => 'activityDateTime')); $this->addDateTime('cancel_date', ts('Cancelled / Refunded Date'), FALSE, array('formatType' => 'activityDateTime')); diff --git a/civicrm/CRM/Contribute/Form/ContributionBase.php b/civicrm/CRM/Contribute/Form/ContributionBase.php index 8be7ccfad4cdb5f7a446a2c8333ce848549efa6d..9465253007306f95158d13b46f07d9e5e06fcb9e 100644 --- a/civicrm/CRM/Contribute/Form/ContributionBase.php +++ b/civicrm/CRM/Contribute/Form/ContributionBase.php @@ -609,8 +609,11 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form { 'total_amount' => 1, 'amount_level' => 1, 'contribution_status_id' => 1, + // @todo replace payment_instrument with payment instrument id. + // both are available now but the id field is the most consistent. 'payment_instrument' => 1, - 'check_number' => 1, + 'payment_instrument_id' => 1, + 'contribution_check_number' => 1, 'financial_type' => 1, ); @@ -633,7 +636,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form { //remove common fields only if profile is not configured for onbehalf/honor if (!in_array($profileContactType, array('honor', 'onbehalf'))) { - $fields = array_diff_assoc($fields, $this->_fields); + $fields = array_diff_key($fields, $this->_fields); } CRM_Core_BAO_Address::checkContactSharedAddressFields($fields, $contactID); diff --git a/civicrm/CRM/Contribute/Form/Search.php b/civicrm/CRM/Contribute/Form/Search.php index e4e2df3d840176cced48e190d5385bed53f984c6..14c3ace64a7742ab57533c369c984787740893f4 100644 --- a/civicrm/CRM/Contribute/Form/Search.php +++ b/civicrm/CRM/Contribute/Form/Search.php @@ -297,20 +297,19 @@ class CRM_Contribute_Form_Search extends CRM_Core_Form_Search { } } - if (!defined('CIVICRM_GROUPTREE')) { - $group = CRM_Utils_Array::value('group', $this->_formValues); - if ($group && !is_array($group)) { - unset($this->_formValues['group']); - $this->_formValues['group'][$group] = 1; - } + $group = CRM_Utils_Array::value('group', $this->_formValues); + if ($group && !is_array($group)) { + unset($this->_formValues['group']); + $this->_formValues['group'][$group] = 1; + } - if ($group && is_array($group)) { - unset($this->_formValues['group']); - foreach ($group as $notImportant => $groupID) { - $this->_formValues['group'][$groupID] = 1; - } + if ($group && is_array($group)) { + unset($this->_formValues['group']); + foreach ($group as $groupID) { + $this->_formValues['group'][$groupID] = 1; } } + } CRM_Core_BAO_CustomValue::fixCustomFieldValue($this->_formValues); diff --git a/civicrm/CRM/Contribute/Form/Task/Batch.php b/civicrm/CRM/Contribute/Form/Task/Batch.php index ca6c15eeb99ec373eb9653b326663f9a007167ba..f1b47a4375ebb2e1518c97cc4fcf1a9ba43050ed 100644 --- a/civicrm/CRM/Contribute/Form/Task/Batch.php +++ b/civicrm/CRM/Contribute/Form/Task/Batch.php @@ -187,7 +187,6 @@ class CRM_Contribute_Form_Task_Batch extends CRM_Contribute_Form_Task { $defaults = array(); foreach ($this->_contributionIds as $contributionId) { - $details[$contributionId] = array(); CRM_Core_BAO_UFGroup::setProfileDefaults(NULL, $this->_fields, $defaults, FALSE, $contributionId, 'Contribute'); } diff --git a/civicrm/CRM/Core/BAO/CustomField.php b/civicrm/CRM/Core/BAO/CustomField.php index 1aff500d455536fccbca7923c93b638c6847072b..82bfee3e06f85f7b84da22756e56324374af02d2 100644 --- a/civicrm/CRM/Core/BAO/CustomField.php +++ b/civicrm/CRM/Core/BAO/CustomField.php @@ -1443,7 +1443,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField { $entityId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_EntityFile', $fileID, 'entity_id', - 'id' + 'file_id' ); list($path) = CRM_Core_BAO_File::path($fileID, $entityId, NULL, NULL); $url = CRM_Utils_System::url('civicrm/file', diff --git a/civicrm/CRM/Core/BAO/CustomGroup.php b/civicrm/CRM/Core/BAO/CustomGroup.php index 703572d2981d6580348d5dafbb18b56f20465cd7..924fb74a2b4d2384b9753a088ad596abe0c92dd9 100644 --- a/civicrm/CRM/Core/BAO/CustomGroup.php +++ b/civicrm/CRM/Core/BAO/CustomGroup.php @@ -1884,12 +1884,6 @@ SELECT IF( EXISTS(SELECT name FROM civicrm_contact_type WHERE name like %1), 1, // add field information foreach ($value['fields'] as $k => $properties) { $properties['element_name'] = "custom_{$k}_-{$groupCount}"; - if ($value = CRM_Utils_Request::retrieve($properties['element_name'], 'String', $form, FALSE, NULL, 'POST')) { - $formValues[$properties['element_name']] = $value; - } - elseif (isset($submittedValues[$properties['element_name']])) { - $properties['element_value'] = $submittedValues[$properties['element_name']]; - } if (isset($properties['customValue']) && !CRM_Utils_System::isNull($properties['customValue']) && !isset($properties['element_value']) @@ -1906,6 +1900,12 @@ SELECT IF( EXISTS(SELECT name FROM civicrm_contact_type WHERE name like %1), 1, } } } + if ($value = CRM_Utils_Request::retrieve($properties['element_name'], 'String', $form, FALSE, NULL, 'POST')) { + $formValues[$properties['element_name']] = $value; + } + elseif (isset($submittedValues[$properties['element_name']])) { + $properties['element_value'] = $submittedValues[$properties['element_name']]; + } unset($properties['customValue']); $formattedGroupTree[$key]['fields'][$k] = $properties; } diff --git a/civicrm/CRM/Core/BAO/EntityTag.php b/civicrm/CRM/Core/BAO/EntityTag.php index 6b4a74e9131e559601d315a101ea43ff7fbbd211..accc5d6d082602e23019fa27aa4321238183ca79 100644 --- a/civicrm/CRM/Core/BAO/EntityTag.php +++ b/civicrm/CRM/Core/BAO/EntityTag.php @@ -81,6 +81,9 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { // dont save the object if it already exists, CRM-1276 if (!$entityTag->find(TRUE)) { + //invoke pre hook + CRM_Utils_Hook::pre('create', 'EntityTag', $params['tag_id'], $params); + $entityTag->save(); //invoke post hook on entityTag @@ -111,6 +114,11 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { * (reference ) an assoc array of name/value pairs. */ public static function del(&$params) { + //invoke pre hook + if (!empty($params['tag_id'])) { + CRM_Utils_Hook::pre('delete', 'EntityTag', $params['tag_id'], $params); + } + $entityTag = new CRM_Core_BAO_EntityTag(); $entityTag->copyValues($params); $entityTag->delete(); @@ -142,6 +150,10 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { $numEntitiesNotAdded = 0; $entityIdsAdded = array(); + //invoke pre hook for entityTag + $preObject = array($entityIds, $entityTable); + CRM_Utils_Hook::pre('create', 'EntityTag', $tagId, $preObject); + foreach ($entityIds as $entityId) { // CRM-17350 - check if we have permission to edit the contact // that this tag belongs to. @@ -216,6 +228,10 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { $numEntitiesNotRemoved = 0; $entityIdsRemoved = array(); + //invoke pre hook for entityTag + $preObject = array($entityIds, $entityTable); + CRM_Utils_Hook::pre('delete', 'EntityTag', $tagId, $preObject); + foreach ($entityIds as $entityId) { // CRM-17350 - check if we have permission to edit the contact // that this tag belongs to. @@ -376,7 +392,10 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { } /** - * Merge two tags: tag B into tag A. + * Merge two tags + * + * Tag A will inherit all of tag B's properties. + * Tag B will be deleted. * * @param int $tagAId * @param int $tagBId @@ -385,8 +404,8 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { */ public function mergeTags($tagAId, $tagBId) { $queryParams = array( - 1 => array($tagBId, 'Integer'), - 2 => array($tagAId, 'Integer'), + 1 => array($tagAId, 'Integer'), + 2 => array($tagBId, 'Integer'), ); // re-compute used_for field @@ -400,19 +419,21 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag { } $usedFor = array_merge($tags["tagA_used_for"], $tags["tagB_used_for"]); $usedFor = implode(',', array_unique($usedFor)); - $tags["tagB_used_for"] = explode(",", $usedFor); + $tags["used_for"] = explode(",", $usedFor); // get all merge queries together $sqls = array( // 1. update entity tag entries "UPDATE IGNORE civicrm_entity_tag SET tag_id = %1 WHERE tag_id = %2", - // 2. update used_for info for tag B - "UPDATE civicrm_tag SET used_for = '{$usedFor}' WHERE id = %1", - // 3. remove tag A, if tag A is getting merged into B + // 2. move children + "UPDATE civicrm_tag SET parent_id = %1 WHERE parent_id = %2", + // 3. update used_for info for tag A & children + "UPDATE civicrm_tag SET used_for = '{$usedFor}' WHERE id = %1 OR parent_id = %1", + // 4. delete tag B "DELETE FROM civicrm_tag WHERE id = %2", - // 4. remove duplicate entity tag records + // 5. remove duplicate entity tag records "DELETE et2.* from civicrm_entity_tag et1 INNER JOIN civicrm_entity_tag et2 ON et1.entity_table = et2.entity_table AND et1.entity_id = et2.entity_id AND et1.tag_id = et2.tag_id WHERE et1.id < et2.id", - // 5. remove orphaned entity_tags + // 6. remove orphaned entity_tags "DELETE FROM civicrm_entity_tag WHERE tag_id = %2", ); $tables = array('civicrm_entity_tag', 'civicrm_tag'); diff --git a/civicrm/CRM/Core/BAO/Tag.php b/civicrm/CRM/Core/BAO/Tag.php index c1b4ae44f41b3c543e4f011b6acdb9cf9a9f2da2..936998aa9919e99741665f694cf8dcccdcf1154e 100644 --- a/civicrm/CRM/Core/BAO/Tag.php +++ b/civicrm/CRM/Core/BAO/Tag.php @@ -395,8 +395,8 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { * (optional) the array that holds all the db ids - we are moving away from this in bao. * signatures * - * @return object - * CRM_Core_DAO_Tag object on success, otherwise null + * @return CRM_Core_DAO_Tag|null + * object on success, otherwise null */ public static function add(&$params, $ids = array()) { $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('tag', $ids)); @@ -411,6 +411,13 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { // get parent details $params['used_for'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $params['parent_id'], 'used_for'); } + elseif (isset($params['used_for']) && is_array($params['used_for'])) { + $params['used_for'] = implode(',', $params['used_for']); + } + + if (isset($params['color']) && strtolower($params['color']) === '#ffffff') { + $params['color'] = ''; + } $tag->copyValues($params); $tag->id = $id; @@ -428,10 +435,11 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { CRM_Utils_Hook::post($hook, 'Tag', $tag->id, $tag); // if we modify parent tag, then we need to update all children - if ($tag->parent_id === 'null') { + $tag->find(TRUE); + if (!$tag->parent_id && $tag->used_for) { CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET used_for=%1 WHERE parent_id = %2", array( - 1 => array($params['used_for'], 'String'), + 1 => array($tag->used_for, 'String'), 2 => array($tag->id, 'Integer'), ) ); diff --git a/civicrm/CRM/Core/BAO/UFGroup.php b/civicrm/CRM/Core/BAO/UFGroup.php index de3cb70ce0dd7fe8bd5fb50f0e19de093dfb635c..272cf8be8964dfa6a05febc51c9bea2beab80983 100644 --- a/civicrm/CRM/Core/BAO/UFGroup.php +++ b/civicrm/CRM/Core/BAO/UFGroup.php @@ -348,9 +348,7 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { $query = self::createUFFieldQuery($group->id, $searchable, $showAll, $visibility, $orderBy); $field = CRM_Core_DAO::executeQuery($query); - $profileType = CRM_Core_BAO_UFField::getProfileType($group->id); - $contactActivityProfile = CRM_Core_BAO_UFField::checkContactActivityProfileType($group->id); - $importableFields = self::getImportableFields($showAll, $profileType, $contactActivityProfile); + $importableFields = self::getProfileFieldMetadata($showAll); list($customFields, $addressCustomFields) = self::getCustomFields($ctype); while ($field->fetch()) { @@ -478,6 +476,7 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { if (isset($field->phone_type_id)) { $name .= "-{$field->phone_type_id}"; } + $fieldMetaData = CRM_Utils_Array::value($name, $importableFields, (isset($importableFields[$field->field_name]) ? $importableFields[$field->field_name] : array())); // No lie: this is bizarre; why do we need to mix so many UFGroup properties into UFFields? // I guess to make field self sufficient with all the required data and avoid additional calls @@ -515,8 +514,15 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { CRM_Utils_Array::value($field->field_name, $importableFields) ), 'skipDisplay' => 0, + 'data_type' => CRM_Utils_Type::getDataTypeFromFieldMetadata($fieldMetaData), + 'bao' => CRM_Utils_Array::value('bao', $fieldMetaData), ); + $formattedField = CRM_Utils_Date::addDateMetadataToField($fieldMetaData, $formattedField); + if (in_array($name, array_keys(self::getNonUpgradedDateFields()))) { + $formattedField['is_legacy_date'] = 1; + } + //adding custom field property if (substr($field->field_name, 0, 6) == 'custom' || substr($field->field_name, 0, 14) === 'address_custom' @@ -527,12 +533,16 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { $formattedField['is_search_range'] = $customFields[$field->field_name]['is_search_range']; // fix for CRM-1994 $formattedField['options_per_line'] = $customFields[$field->field_name]['options_per_line']; - $formattedField['data_type'] = $customFields[$field->field_name]['data_type']; $formattedField['html_type'] = $customFields[$field->field_name]['html_type']; if (CRM_Utils_Array::value('html_type', $formattedField) == 'Select Date') { $formattedField['date_format'] = $customFields[$field->field_name]['date_format']; $formattedField['time_format'] = $customFields[$field->field_name]['time_format']; + $formattedField['php_datetime_format'] = CRM_Utils_Date::getPhpDateFormatFromInputStyleDateFormat($customFields[$field->field_name]['date_format']); + if ($formattedField['time_format']) { + $formattedField['php_datetime_format'] .= ' H-i-s'; + } + $formattedField['is_datetime_field'] = TRUE; } $formattedField['is_multi_summary'] = $field->is_multi_summary; @@ -636,13 +646,24 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { } /** + * Get a list of filtered field metadata. + * + * @deprecated use getProfileFieldMetadata + * * @param $showAll * @param $profileType * @param $contactActivityProfile + * @param bool $filterMode + * Filter mode means you are using importable fields for filtering rather than just getting metadata. + * With filter mode = FALSE BOTH activity fields and component fields are returned. + * I can't see why you would ever want to use this function in filter mode as the component fields are + * still unfiltered. However, I feel scared enough to leave it as it is. I have marked this function as + * deprecated and am recommending the wrapper 'getProfileFieldMetadata' in order to try to + * send this confusion to history. * * @return array */ - protected static function getImportableFields($showAll, $profileType, $contactActivityProfile) { + protected static function getImportableFields($showAll, $profileType, $contactActivityProfile, $filterMode = TRUE) { if (!$showAll) { $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, FALSE, FALSE, TRUE, TRUE); } @@ -650,15 +671,20 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, TRUE, FALSE, TRUE, TRUE); } - if ($profileType == 'Activity' || $contactActivityProfile) { - $componentFields = CRM_Activity_BAO_Activity::getProfileFields(); + $activityFields = CRM_Activity_BAO_Activity::getProfileFields(); + $componentFields = CRM_Core_Component::getQueryFields(); + if ($filterMode == TRUE) { + if ($profileType == 'Activity' || $contactActivityProfile) { + $importableFields = array_merge($importableFields, $activityFields); + } + else { + $importableFields = array_merge($importableFields, $componentFields); + } } else { - $componentFields = CRM_Core_Component::getQueryFields(); + $importableFields = array_merge($importableFields, $activityFields, $componentFields); } - $importableFields = array_merge($importableFields, $componentFields); - $importableFields['group']['title'] = ts('Group(s)'); $importableFields['group']['where'] = NULL; $importableFields['tag']['title'] = ts('Tag(s)'); @@ -666,6 +692,19 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { return $importableFields; } + /** + * Get the metadata for all potential profile fields. + * + * @param bool $isIncludeInactive + * Should disabled fields be included. + * + * @return array + * Field metadata for all fields that might potentially be in a profile. + */ + protected static function getProfileFieldMetadata($isIncludeInactive) { + return self::getImportableFields($isIncludeInactive, NULL, NULL, NULL, TRUE); + } + /** * Get the fields relating to locations. * @@ -1039,19 +1078,6 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { $idx = $name . '_id'; $params[$index] = $details->$idx; } - elseif ($name === 'preferred_communication_method') { - $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method'); - $compref = array(); - $pref = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name); - - foreach ($pref as $k) { - if ($k) { - $compref[] = $communicationFields[$k]; - } - } - $params[$index] = $details->$name; - $values[$index] = implode(',', $compref); - } elseif ($name === 'preferred_language') { $params[$index] = $details->$name; $values[$index] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name); @@ -1063,7 +1089,7 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { foreach ($groups as $g) { // CRM-8362: User and User Admin visibility groups should be included in display if user has // VIEW permission on that group - $groupPerm = CRM_Contact_BAO_Group::checkPermission($g['group_id'], $g['title']); + $groupPerm = CRM_Contact_BAO_Group::checkPermission($g['group_id'], TRUE); if ($g['visibility'] != 'User and User Admin Only' || CRM_Utils_Array::key(CRM_Core_Permission::VIEW, $groupPerm) @@ -1197,6 +1223,7 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup { 'membership_end_date', 'join_date', ))) { + // @todo this set should be determined from metadata, not hard-coded. $values[$index] = CRM_Utils_Date::customFormat($details->$name); $params[$index] = CRM_Utils_Date::isoToMysql($details->$name); } @@ -1869,6 +1896,7 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'address_options', TRUE, NULL, TRUE ); + $legacyHandledDateFields = self::getNonUpgradedDateFields(); if (substr($fieldName, 0, 14) === 'state_province') { $form->addChainSelect($name, array('label' => $title, 'required' => $required)); @@ -1931,15 +1959,8 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) } } } - elseif (($fieldName === 'birth_date') || ($fieldName === 'deceased_date')) { - $form->addDate($name, $title, $required, array('formatType' => 'birth')); - } - elseif (in_array($fieldName, array( - 'membership_start_date', - 'membership_end_date', - 'join_date', - ))) { - $form->addDate($name, $title, $required, array('formatType' => 'activityDate')); + elseif (isset($legacyHandledDateFields[$fieldName])) { + $form->addDate($name, $title, $required, array('formatType' => $legacyHandledDateFields[$fieldName])); } elseif (CRM_Utils_Array::value('name', $field) == 'membership_type') { list($orgInfo, $types) = CRM_Member_BAO_MembershipType::getMembershipTypeInfo(); @@ -2115,14 +2136,6 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title); } } - elseif (in_array($fieldName, array( - 'receive_date', - 'receipt_date', - 'thankyou_date', - 'cancel_date', - ))) { - $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime')); - } elseif ($fieldName == 'send_receipt') { $form->addElement('checkbox', $name, $title); } @@ -2194,9 +2207,6 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) ) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"' ); } - elseif ($fieldName == 'participant_register_date') { - $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime')); - } elseif ($fieldName == 'activity_status_id') { $form->add('select', $name, $title, array( @@ -2211,9 +2221,6 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) ) + CRM_Campaign_PseudoConstant::engagementLevel(), $required ); } - elseif ($fieldName == 'activity_date_time') { - $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime')); - } elseif ($fieldName == 'participant_status') { $cond = NULL; if ($online == TRUE) { @@ -2311,6 +2318,30 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) } } + /** + * Get fields that have not been upgraded to use datepicker. + * + * Fields that use the old code have jcalendar in the tpl and + * the form uses a customised format. We are moving towards datepicker + * which among other things passes dates back and forth using a standardised + * format. Remove fields from here as they are tested and converted. + */ + static public function getNonUpgradedDateFields() { + return array( + 'birth_date' => 'birth', + 'deceased_date' => 'birth', + 'membership_start_date' => 'activityDate', + 'membership_end_date' => 'activityDate', + 'join_date' => 'activityDate', + 'receive_date' => 'activityDateTime', + 'receipt_date' => 'activityDateTime', + 'thankyou_date' => 'activityDateTime', + 'cancel_date' => 'activityDateTime', + 'participant_register_date' => 'activityDateTime', + 'activity_date_time' => 'activityDateTime', + ); + } + /** * Set profile defaults. * @@ -2383,7 +2414,7 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) $defaults[$fldName] = $details['worldregion_id']; } elseif ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($name)) { - //fix for custom fields + // @todo retrieving the custom fields here seems obsolete - $field holds more data for the fields. $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $details)); // hack to add custom data for components @@ -3254,6 +3285,7 @@ AND ( entity_id IS NULL OR entity_id <= 0 ) } $formattedGroupTree = array(); + // @todo - as we put these on datepicker they need to be removed from here. $dateTimeFields = array( 'participant_register_date', 'activity_date_time', diff --git a/civicrm/CRM/Core/BAO/UFMatch.php b/civicrm/CRM/Core/BAO/UFMatch.php index bfd6a9b5cdfba3c1abd4e1e9068717573d5983b0..f20be6680d358810a9a5ca71e877c0d2f77f0f49 100644 --- a/civicrm/CRM/Core/BAO/UFMatch.php +++ b/civicrm/CRM/Core/BAO/UFMatch.php @@ -356,9 +356,10 @@ AND domain_id = %4 * Id of the contact to update. */ public static function updateUFName($contactId) { - if (!$contactId) { + if (!Civi::settings()->get('syncCMSEmail') || !$contactId) { return; } + $config = CRM_Core_Config::singleton(); $ufName = CRM_Contact_BAO_Contact::getPrimaryEmail($contactId); @@ -420,6 +421,11 @@ AND domain_id = %4 $ufmatch->uf_name = $emailAddress; CRM_Core_BAO_UFMatch::create((array) $ufmatch); + // If CMS integration is disabled skip Civi email update if CMS user email is changed + if (Civi::settings()->get('syncCMSEmail') == FALSE) { + return; + } + //check if the primary email for the contact exists //$contactDetails[1] - email //$contactDetails[3] - email id diff --git a/civicrm/CRM/Core/CodeGen/Specification.php b/civicrm/CRM/Core/CodeGen/Specification.php index dbebd3291ff1e3f1a0e7bd6a4f2e4c6626c6dae1..2a94606859b04cf3beefd79a7ac5506379ce0bd6 100644 --- a/civicrm/CRM/Core/CodeGen/Specification.php +++ b/civicrm/CRM/Core/CodeGen/Specification.php @@ -365,7 +365,7 @@ class CRM_Core_CodeGen_Specification { if (!empty($field['html'])) { $validOptions = array( 'type', - 'format', + 'formatType', /* Fixme: prior to CRM-13497 these were in a flat structure // CRM-13497 moved them to be nested within 'html' but there's no point // making that change in the DAOs right now since we are in the process of diff --git a/civicrm/CRM/Core/DAO/AllCoreTables.data.php b/civicrm/CRM/Core/DAO/AllCoreTables.data.php index d64334f5219efcbf1500c111cd4a9300d93d5d6e..7ca1c70776f85a1a2bc8d906bf4534cb6671ebfc 100644 --- a/civicrm/CRM/Core/DAO/AllCoreTables.data.php +++ b/civicrm/CRM/Core/DAO/AllCoreTables.data.php @@ -24,7 +24,7 @@ | see the CiviCRM license FAQ at http://civicrm.org/licensing | +--------------------------------------------------------------------+ */ -// (GenCodeChecksum:616d65664572d5eaffb63dd660d6ff36) +// (GenCodeChecksum:9f38a12c446ece781c1ef9c46dd95a5d) return array( 'CRM_Core_DAO_AddressFormat' => array( 'name' => 'AddressFormat', diff --git a/civicrm/CRM/Core/Error.php b/civicrm/CRM/Core/Error.php index 07dfc50b8745acea10646bec94a9791ad6397e7f..81b470bbc0260adc65d70b8ffb018efc9a0210c4 100644 --- a/civicrm/CRM/Core/Error.php +++ b/civicrm/CRM/Core/Error.php @@ -310,6 +310,11 @@ class CRM_Core_Error extends PEAR_ErrorStack { /** * Display an error page with an error message describing what happened. * + * @deprecated + * This is a really annoying function. We ⤠exceptions. Be exceptional! + * + * @see CRM-20181 + * * @param string $message * The error message. * @param string $code diff --git a/civicrm/CRM/Core/Form.php b/civicrm/CRM/Core/Form.php index fadce93d65a196bd7b2ed04ebe999ddccfe49726..68d4ceabea4575ac43618b789175d68075324b29 100644 --- a/civicrm/CRM/Core/Form.php +++ b/civicrm/CRM/Core/Form.php @@ -337,6 +337,8 @@ class CRM_Core_Form extends HTML_QuickForm_Page { * @param bool $required * @param array $extra * (attributes for select elements). + * For datepicker elements this is consistent with the data + * from CRM_Utils_Date::getDatePickerExtra * * @return HTML_QuickForm_Element * Could be an error object diff --git a/civicrm/CRM/Core/OptionGroup.php b/civicrm/CRM/Core/OptionGroup.php index 8fdecdfdb5f91ba4ddeeff7e2d5540b4fd064415..1227803a5fbeb173d2898a5d63ec81e80e4e0118 100644 --- a/civicrm/CRM/Core/OptionGroup.php +++ b/civicrm/CRM/Core/OptionGroup.php @@ -109,6 +109,7 @@ class CRM_Core_OptionGroup { * @param string $keyColumnName * the column to use for 'key'. * @param string $orderBy + * the column to use for ordering. * * @return array * The values as specified by the params @@ -120,7 +121,7 @@ class CRM_Core_OptionGroup { $orderBy = 'weight' ) { $cache = CRM_Utils_Cache::singleton(); - $cacheKey = self::createCacheKey($name, $flip, $grouping, $localize, $condition, $labelColumnName, $onlyActive, $keyColumnName); + $cacheKey = self::createCacheKey($name, $flip, $grouping, $localize, $condition, $labelColumnName, $onlyActive, $keyColumnName, $orderBy); if (!$fresh) { // Fetch from static var @@ -144,6 +145,14 @@ WHERE v.option_group_id = g.id if ($onlyActive) { $query .= " AND v.is_active = 1 "; + // Only show options for enabled components + $componentClause = ' v.component_id IS NULL '; + $enabledComponents = CRM_Core_Config::singleton()->enableComponents; + if ($enabledComponents) { + $enabledComponents = '"' . implode('","', $enabledComponents) . '"'; + $componentClause .= " OR v.component_id IN (SELECT id FROM civicrm_component WHERE name IN ($enabledComponents)) "; + } + $query .= " AND ($componentClause) "; } if (in_array($name, self::$_domainIDGroups)) { $query .= " AND v.domain_id = " . CRM_Core_Config::domainID(); @@ -253,9 +262,9 @@ WHERE v.option_group_id = g.id } /** - * Lookup titles OR ids for a set of option_value populated fields. The retrieved value - * is assigned a new fieldname by id or id's by title - * (each within a specificied option_group) + * Lookup titles OR ids for a set of option_value populated fields. The + * retrieved value is assigned a new field name by id or id's by title + * (each within a specified option_group). * * @param array $params * Reference array of values submitted by the form. Based on. @@ -265,14 +274,13 @@ WHERE v.option_group_id = g.id * If $flip = true, adds actual field name => id * * @param array $names - * Reference array of fieldnames we want transformed. + * Array of field names we want transformed. * Array key = 'postName' (field name submitted by form in $params). * Array value = array('newName' => $newName, 'groupName' => $groupName). * - * * @param bool $flip */ - public static function lookupValues(&$params, &$names, $flip = FALSE) { + public static function lookupValues(&$params, $names, $flip = FALSE) { foreach ($names as $postName => $value) { // See if $params field is in $names array (i.e. is a value that we need to lookup) if ($postalName = CRM_Utils_Array::value($postName, $params)) { diff --git a/civicrm/CRM/Core/Payment/PayPalIPN.php b/civicrm/CRM/Core/Payment/PayPalIPN.php index f4d116ae39a1a61e25b29da98a7d9ac06c1972ee..9aa58748696ecd29312f9e9baa135792d548de83 100644 --- a/civicrm/CRM/Core/Payment/PayPalIPN.php +++ b/civicrm/CRM/Core/Payment/PayPalIPN.php @@ -340,7 +340,7 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN { $paymentProcessorID = $this->retrieve('processor_id', 'Integer', FALSE); if (empty($paymentProcessorID)) { $processorParams = array( - 'user_name' => $this->retrieve('receiver_email', 'String', FALSE), + 'user_name' => $this->retrieve('business', 'String', FALSE), 'payment_processor_type_id' => CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', 'PayPal_Standard', 'id', 'name'), 'is_test' => empty($input['is_test']) ? 0 : 1, ); diff --git a/civicrm/CRM/Core/SelectValues.php b/civicrm/CRM/Core/SelectValues.php index ba24f9d6a8dd757ed755bae92dd0cb34aa21f887..344219ef5aba0beb9c0b28f5e5179868253bd737 100644 --- a/civicrm/CRM/Core/SelectValues.php +++ b/civicrm/CRM/Core/SelectValues.php @@ -311,7 +311,8 @@ class CRM_Core_SelectValues { * @return array * the date array */ - public static function date($type = NULL, $format = NULL, $minOffset = NULL, $maxOffset = NULL) { + public static function date($type = NULL, $format = NULL, $minOffset = NULL, $maxOffset = NULL, $context = 'display') { + // These options are deprecated. Definitely not used in datepicker. Possibly not even in jcalendar+addDateTime. $date = array( 'addEmptyOption' => TRUE, 'emptyOptionText' => ts('- select -'), @@ -328,25 +329,34 @@ class CRM_Core_SelectValues { if (!$dao->find(TRUE)) { CRM_Core_Error::fatal(); } - } + if (!$maxOffset) { + $maxOffset = $dao->end; + } + if (!$minOffset) { + $minOffset = $dao->start; + } - if ($type == 'creditCard') { - $minOffset = $dao->start; - $maxOffset = $dao->end; $date['format'] = $dao->date_format; - $date['addEmptyOption'] = TRUE; - $date['emptyOptionText'] = ts('- select -'); - $date['emptyOptionValue'] = ''; + $date['time'] = (bool) $dao->time_format; } if (empty($date['format'])) { - $date['format'] = 'M d'; + if ($context == 'Input') { + $date['format'] = Civi::settings()->get('dateInputFormat'); + $date['php_datetime_format'] = self::datePluginToPHPFormats(Civi::settings()->get('dateInputFormat')); + } + else { + $date['format'] = 'M d'; + } } } + if (!isset($date['time'])) { + $date['time'] = FALSE; + } $year = date('Y'); - $date['minYear'] = $year - $minOffset; - $date['maxYear'] = $year + $maxOffset; + $date['minYear'] = $year - (int) $minOffset; + $date['maxYear'] = $year + (int) $maxOffset; return $date; } diff --git a/civicrm/CRM/Core/Smarty/plugins/modifier.crmDate.php b/civicrm/CRM/Core/Smarty/plugins/modifier.crmDate.php index 11b001abd7592f069447f9a1db86e588b58ff821..8e2afb6a59b76563fe7733e146908b7950ec5539 100644 --- a/civicrm/CRM/Core/Smarty/plugins/modifier.crmDate.php +++ b/civicrm/CRM/Core/Smarty/plugins/modifier.crmDate.php @@ -56,6 +56,10 @@ function smarty_modifier_crmDate($dateString, $dateFormat = NULL, $onlyTime = FA $config = CRM_Core_Config::singleton(); $dateFormat = $config->dateformatTime; } + // Handle possibility we only have a date function style date format. + if ($dateFormat && !stristr($dateFormat, '%')) { + return date($dateFormat, strtotime($dateString)); + } return CRM_Utils_Date::customFormat($dateString, $dateFormat); } diff --git a/civicrm/CRM/Core/xml/Menu/Admin.xml b/civicrm/CRM/Core/xml/Menu/Admin.xml index 718e8149790c685d77e74c708f41cf3b08acd038..1e913a2af253aced5660b009b59bc278867ff22e 100644 --- a/civicrm/CRM/Core/xml/Menu/Admin.xml +++ b/civicrm/CRM/Core/xml/Menu/Admin.xml @@ -653,11 +653,6 @@ <page_callback>CRM_Admin_Page_AJAX::getStatusMsg</page_callback> <access_arguments>access CiviCRM</access_arguments> </item> - <item> - <path>civicrm/ajax/mergeTags</path> - <page_callback>CRM_Admin_Page_AJAX::mergeTags</page_callback> - <access_arguments>access CiviCRM</access_arguments> - </item> <item> <path>civicrm/admin/price</path> <title>Price Sets</title> @@ -687,11 +682,6 @@ <title>Price Field Options</title> <page_callback>CRM_Price_Page_Option</page_callback> </item> - <item> - <path>civicrm/ajax/mergeTagList</path> - <page_callback>CRM_Admin_Page_AJAX::mergeTagList</page_callback> - <access_arguments>access CiviCRM</access_arguments> - </item> <item> <path>civicrm/admin/tplstrings/add</path> <page_callback>CRM_Admin_Form_Persistent</page_callback> diff --git a/civicrm/CRM/Core/xml/Menu/Tag.xml b/civicrm/CRM/Core/xml/Menu/Tag.xml index 104f89680643d545eb1c23d121331d1668ab5434..e05e6eed8b4a21a517d62f2b51656e9b9bb2e46d 100644 --- a/civicrm/CRM/Core/xml/Menu/Tag.xml +++ b/civicrm/CRM/Core/xml/Menu/Tag.xml @@ -12,10 +12,21 @@ <weight>25</weight> </item> <item> - <path>civicrm/tag/add</path> + <path>civicrm/tag/edit</path> <title>New Tag</title> - <page_callback>CRM_Tag_Page_Tag</page_callback> + <page_callback>CRM_Tag_Form_Edit</page_callback> <path_arguments>action=add</path_arguments> <access_arguments>administer CiviCRM;manage tags</access_arguments> </item> + <item> + <path>civicrm/tag/merge</path> + <title>Merge Tags</title> + <page_callback>CRM_Tag_Form_Merge</page_callback> + <access_arguments>administer CiviCRM;manage tags</access_arguments> + </item> + <item> + <path>civicrm/ajax/tagTree</path> + <page_callback>CRM_Admin_Page_AJAX::getTagTree</page_callback> + <access_arguments>administer CiviCRM;manage tags</access_arguments> + </item> </menu> diff --git a/civicrm/CRM/Dashlet/Page/GettingStarted.php b/civicrm/CRM/Dashlet/Page/GettingStarted.php index 7811256a219d615d1ff76d878ab61a7448933ad8..775726b06d946afe9a94770ee6d86242bef7c6ac 100644 --- a/civicrm/CRM/Dashlet/Page/GettingStarted.php +++ b/civicrm/CRM/Dashlet/Page/GettingStarted.php @@ -143,7 +143,7 @@ class CRM_Dashlet_Page_GettingStarted extends CRM_Core_Page { if (!empty(self::$_tokens[$categories][$token])) { $value = self::$_tokens[$categories][$token]; if ($categories == 'crmurl') { - $value = CRM_Utils_System::url($value, "reset=1", FALSE, NULL, TRUE, TRUE); + $value = CRM_Utils_System::url($value, "reset=1"); } } CRM_Utils_Token::token_replace($categories, $token, $value, $str); diff --git a/civicrm/CRM/Dedupe/Merger.php b/civicrm/CRM/Dedupe/Merger.php index 183dd63b7dd1ab527a7a4cfce5803eaadac079be..1905a85fdc0c4669c47669b95db1749e4046f0b6 100644 --- a/civicrm/CRM/Dedupe/Merger.php +++ b/civicrm/CRM/Dedupe/Merger.php @@ -589,8 +589,6 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * Helps decide how to behave when there are conflicts. * A 'safe' value skips the merge if there are any un-resolved conflicts, wheras 'aggressive' * mode does a force merge. - * @param bool $autoFlip to let api decide which contact to retain and which to delete. - * Whether to let api decide which contact to retain and which to delete. * @param int $batchLimit number of merges to carry out in one batch. * @param int $isSelected if records with is_selected column needs to be processed. * @@ -602,7 +600,7 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * * @return array|bool */ - public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $autoFlip = TRUE, $batchLimit = 1, $isSelected = 2, $criteria = array(), $checkPermissions = TRUE) { + public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = array(), $checkPermissions = TRUE) { $redirectForPerformance = ($batchLimit > 1) ? TRUE : FALSE; $reloadCacheIfEmpty = (!$redirectForPerformance && $isSelected == 2); $dupePairs = self::getDuplicatePairs($rgid, $gid, $reloadCacheIfEmpty, $batchLimit, $isSelected, '', ($mode == 'aggressive'), $criteria, $checkPermissions); @@ -614,7 +612,7 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m 'join' => self::getJoinOnDedupeTable(), 'where' => self::getWhereString($batchLimit, $isSelected), ); - return CRM_Dedupe_Merger::merge($dupePairs, $cacheParams, $mode, $autoFlip, $redirectForPerformance, $checkPermissions); + return CRM_Dedupe_Merger::merge($dupePairs, $cacheParams, $mode, $redirectForPerformance, $checkPermissions); } /** @@ -748,8 +746,6 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * Helps decide how to behave when there are conflicts. * A 'safe' value skips the merge if there are any un-resolved conflicts. * Does a force merge otherwise (aggressive mode). - * @param bool $autoFlip to let api decide which contact to retain and which to delete. - * Whether to let api decide which contact to retain and which to delete. * * @param bool $redirectForPerformance * Redirect to a url for batch processing. @@ -760,7 +756,7 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * @return array|bool */ public static function merge($dupePairs = array(), $cacheParams = array(), $mode = 'safe', - $autoFlip = TRUE, $redirectForPerformance = FALSE, $checkPermissions = TRUE + $redirectForPerformance = FALSE, $checkPermissions = TRUE ) { $cacheKeyString = CRM_Utils_Array::value('cache_key_string', $cacheParams); $resultStats = array('merged' => array(), 'skipped' => array()); diff --git a/civicrm/CRM/Event/BAO/Participant.php b/civicrm/CRM/Event/BAO/Participant.php index 25347945cd7f711da670e02adf03d1daaeae6bbc..2b4dbc402ad42cc21e104676beae8afec80e585b 100644 --- a/civicrm/CRM/Event/BAO/Participant.php +++ b/civicrm/CRM/Event/BAO/Participant.php @@ -648,6 +648,7 @@ GROUP BY participant.event_id 'title' => ts('Participant Note'), 'name' => 'participant_note', 'headerPattern' => '/(participant.)?note$/i', + 'type' => 'text', ), ); diff --git a/civicrm/CRM/Event/DAO/Participant.php b/civicrm/CRM/Event/DAO/Participant.php index b497955e61579d90243b701ea8506c9e74b68b6a..8da34792f3d23bc1eaf6d8a6b4081618f707a1d5 100644 --- a/civicrm/CRM/Event/DAO/Participant.php +++ b/civicrm/CRM/Event/DAO/Participant.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Event/Participant.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:3c53d2d7a62cf0428fef11b9df02fcd2) + * (GenCodeChecksum:87c3d1afa18e39e10ba019d773eb6ce8) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -310,7 +310,7 @@ class CRM_Event_DAO_Participant extends CRM_Core_DAO { 'bao' => 'CRM_Event_BAO_Participant', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDateTime', + 'formatType' => 'activityDateTime', ) , ) , 'participant_source' => array( diff --git a/civicrm/CRM/Event/Form/EventFees.php b/civicrm/CRM/Event/Form/EventFees.php index 0a01313035e396ccc0efc0a843ddc7d216ac5815..036165c28af6850fb85cfd6a1c3359b87916231b 100644 --- a/civicrm/CRM/Event/Form/EventFees.php +++ b/civicrm/CRM/Event/Form/EventFees.php @@ -407,7 +407,7 @@ SELECT id, html_type && !CRM_Utils_Array::value('fee', $form->_values) && CRM_Utils_Array::value('snippet', $_REQUEST) == CRM_Core_Smarty::PRINT_NOFORM ) { - $form->assign('isFTPermissionDenied', TRUE); + CRM_Core_Session::setStatus(ts('You do not have all the permissions needed for this page.'), 'Permission Denied', 'error'); return FALSE; } if ($form->_mode) { diff --git a/civicrm/CRM/Event/Form/Participant.php b/civicrm/CRM/Event/Form/Participant.php index 876e008096805ecf507f60f9015524f4cc0e9a9b..06216727c8fb8fe582f52b59a187736e60dcc438 100644 --- a/civicrm/CRM/Event/Form/Participant.php +++ b/civicrm/CRM/Event/Form/Participant.php @@ -820,6 +820,7 @@ class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment if (empty($values['payment_instrument_id'])) { $errorMsg['payment_instrument_id'] = ts('Payment Method is a required field.'); } + CRM_Price_BAO_PriceField::priceSetValidation($values['priceSetId'], $values, $errorMsg); } // validate contribution status for 'Failed'. diff --git a/civicrm/CRM/Event/Form/Registration.php b/civicrm/CRM/Event/Form/Registration.php index 5143206ee79b0900640495e3c5d7acd00bd5368b..cf567cc3da36cfeaddddd41cc0e3d94f88268c9d 100644 --- a/civicrm/CRM/Event/Form/Registration.php +++ b/civicrm/CRM/Event/Form/Registration.php @@ -1467,7 +1467,7 @@ WHERE v.option_group_id = g.id $startDate && $startDate >= $now ) { - CRM_Core_Error::statusBounce(ts('Registration for this event begins on %1', array(1 => CRM_Utils_Date::customFormat(CRM_Utils_Array::value('registration_start_date', $this->_values['event'])))), $redirect); + CRM_Core_Error::statusBounce(ts('Registration for this event begins on %1', array(1 => CRM_Utils_Date::customFormat(CRM_Utils_Array::value('registration_start_date', $this->_values['event'])))), $redirect, ts('Sorry')); } $regEndDate = CRM_Utils_Date::processDate(CRM_Utils_Array::value('registration_end_date', @@ -1479,7 +1479,7 @@ WHERE v.option_group_id = g.id if (empty($regEndDate)) { $endDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('event_end_date', $this->_values['event'])); } - CRM_Core_Error::statusBounce(ts('Registration for this event ended on %1', array(1 => $endDate)), $redirect); + CRM_Core_Error::statusBounce(ts('Registration for this event ended on %1', array(1 => $endDate)), $redirect, ts('Sorry')); } } diff --git a/civicrm/CRM/Event/Form/Registration/Confirm.php b/civicrm/CRM/Event/Form/Registration/Confirm.php index 0f4c774d74980ce8047ea9ceeb319fa0e33a5169..155f8e6c136921e98d65a712b58dc9fa64a76568 100644 --- a/civicrm/CRM/Event/Form/Registration/Confirm.php +++ b/civicrm/CRM/Event/Form/Registration/Confirm.php @@ -573,14 +573,10 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration { } if (is_object($payment)) { - try { - $result = $payment->doPayment($value); - $value = array_merge($value, $result); - } - catch (\Civi\Payment\Exception\PaymentProcessorException $e) { - CRM_Core_Session::singleton()->setStatus($e->getMessage()); - CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}")); - } + // Not quite sure why we don't just user $value since it contains the data + // from result + // @todo ditch $result & retest. + list($result, $value) = $this->processPayment($payment, $value); } else { CRM_Core_Error::fatal($paymentObjError); @@ -643,9 +639,9 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration { !$this->_allowWaitlist && !$this->_requireApproval ) { // transactionID & receive date required while building email template - $this->assign('trxn_id', $value['trxn_id']); - $this->assign('receive_date', CRM_Utils_Date::mysqlToIso($value['receive_date'])); - $this->set('receiveDate', CRM_Utils_Date::mysqlToIso($value['receive_date'])); + $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $value)); + $this->assign('receive_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value))); + $this->set('receiveDate', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value))); $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value)); } } @@ -824,7 +820,8 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration { // call postprocess hook before leaving $this->postProcessHook(); // this does not return - $payment->doPayment($primaryParticipant, 'event'); + + $this->processPayment($payment, $primaryParticipant); } else { CRM_Core_Error::fatal($paymentObjError); @@ -1306,4 +1303,25 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration { $form->postProcess(); } + /** + * Process the payment, redirecting back to the page on error. + * + * @param $payment + * @param $value + * + * @return array + */ + private function processPayment($payment, $value) { + try { + $result = $payment->doPayment($value, 'event'); + return array($result, $value); + } + catch (\Civi\Payment\Exception\PaymentProcessorException $e) { + Civi::log()->error('Payment processor exception: ' . $e->getMessage()); + CRM_Core_Session::singleton()->setStatus($e->getMessage()); + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}")); + } + return array(); + } + } diff --git a/civicrm/CRM/Event/Form/Registration/Register.php b/civicrm/CRM/Event/Form/Registration/Register.php index 50999a089b561041a94a2ac76a15008eaf1e7103..6bc629a735ca145523d10211bf45d0f718f6e7e8 100644 --- a/civicrm/CRM/Event/Form/Registration/Register.php +++ b/civicrm/CRM/Event/Form/Registration/Register.php @@ -1015,6 +1015,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { else { $submittedLineItems = array($lineItem); } + $submittedLineItems = array_filter($submittedLineItems); $this->set('lineItem', $submittedLineItems); $this->set('lineItemParticipantsCount', array($primaryParticipantCount)); } diff --git a/civicrm/CRM/Export/BAO/Export.php b/civicrm/CRM/Export/BAO/Export.php index cb0c0c762c4b9a109ceb62ad4c6741be4f3d6851..22fa793331c22891f67607bafd011b3e364eb77c 100644 --- a/civicrm/CRM/Export/BAO/Export.php +++ b/civicrm/CRM/Export/BAO/Export.php @@ -721,8 +721,6 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c } } - $multipleSelectFields = array('preferred_communication_method' => 1); - $addPaymentHeader = FALSE; $paymentDetails = array(); @@ -790,7 +788,6 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c $query->convertToPseudoNames($iterationDAO); //first loop through output columns so that we return what is required, and in same order. - $relationshipField = 0; foreach ($outputColumns as $field => $value) { // add im_provider to $dao object @@ -868,12 +865,6 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c } $field = $field . '_'; - if (array_key_exists($relationField, $multipleSelectFields)) { - $param = array($relationField => $fieldValue); - $names = array($relationField => array('newName' => $relationField, 'groupName' => $relationField)); - CRM_Core_OptionGroup::lookupValues($param, $names, FALSE); - $fieldValue = $param[$relationField]; - } if (is_object($relDAO) && $relationField == 'id') { $row[$field . $relationField] = $relDAO->contact_id; } @@ -949,22 +940,6 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c if ($cfID = CRM_Core_BAO_CustomField::getKeyID($field)) { $row[$field] = CRM_Core_BAO_CustomField::displayValue($fieldValue, $cfID); } - elseif (array_key_exists($field, $multipleSelectFields)) { - //option group fixes - $paramsNew = array($field => $fieldValue); - if ($field == 'test_tutoring') { - $name = array($field => array('newName' => $field, 'groupName' => 'test')); - // for readers group - } - elseif (substr($field, 0, 4) == 'cmr_') { - $name = array($field => array('newName' => $field, 'groupName' => substr($field, 0, -3))); - } - else { - $name = array($field => array('newName' => $field, 'groupName' => $field)); - } - CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE); - $row[$field] = $paramsNew[$field]; - } elseif (in_array($field, array( 'email_greeting', diff --git a/civicrm/CRM/Financial/BAO/FinancialType.php b/civicrm/CRM/Financial/BAO/FinancialType.php index 538b01ccd072594157c4d5dbae465d83c4c460c0..919b221707d63cc31f8f4bbd0ef3273726e49e12 100644 --- a/civicrm/CRM/Financial/BAO/FinancialType.php +++ b/civicrm/CRM/Financial/BAO/FinancialType.php @@ -395,7 +395,33 @@ class CRM_Financial_BAO_FinancialType extends CRM_Financial_DAO_FinancialType { } /** - * Check if FT-ACL is turned on or off + * Check if the logged in user has permission to edit the given financial type. + * + * This is called when determining if they can edit things like option values + * in price sets. At the moment it is not possible to change an option value from + * a type you do not have permission to to a type that you do. + * + * @todo it is currently not possible to edit disabled types if you have ACLs on. + * Do ACLs still apply once disabled? That question should be resolved if tackling + * that gap. + * + * @param int $financialTypeID + * + * @return bool + */ + public static function checkPermissionToEditFinancialType($financialTypeID) { + if (!self::isACLFinancialTypeStatus()) { + return TRUE; + } + // @todo consider adding back in disabled types here. + CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialTypes, CRM_Core_Action::UPDATE); + return isset($financialTypes[$financialTypeID]); + } + + /** + * Check if FT-ACL is turned on or off. + * + * @todo rename this function e.g isFinancialTypeACLsEnabled. * * @return bool */ diff --git a/civicrm/CRM/Financial/DAO/FinancialTrxn.php b/civicrm/CRM/Financial/DAO/FinancialTrxn.php index d7f37ea86a80795ff9a808e9aa1b696791941386..2a13482928053b129850c7595615ed4e74fc272b 100644 --- a/civicrm/CRM/Financial/DAO/FinancialTrxn.php +++ b/civicrm/CRM/Financial/DAO/FinancialTrxn.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Financial/FinancialTrxn.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:f8e72183039a2faadf244264d5f5da22) + * (GenCodeChecksum:52a627d344bca95d30eb8b22aad1e245) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -133,12 +133,24 @@ class CRM_Financial_DAO_FinancialTrxn extends CRM_Core_DAO { * @var int unsigned */ public $payment_instrument_id; + /** + * FK to accept_creditcard option group values + * + * @var int unsigned + */ + public $card_type; /** * Check number * * @var string */ public $check_number; + /** + * Last 4 digits of credit card + * + * @var int unsigned + */ + public $pan_truncation; /** * Class constructor. */ @@ -371,6 +383,22 @@ class CRM_Financial_DAO_FinancialTrxn extends CRM_Core_DAO { 'optionEditPath' => 'civicrm/admin/options/payment_instrument', ) ) , + 'financial_trxn_card_type' => array( + 'name' => 'card_type', + 'type' => CRM_Utils_Type::T_INT, + 'title' => ts('Card Type') , + 'description' => 'FK to accept_creditcard option group values', + 'table_name' => 'civicrm_financial_trxn', + 'entity' => 'FinancialTrxn', + 'bao' => 'CRM_Financial_DAO_FinancialTrxn', + 'html' => array( + 'type' => 'Select', + ) , + 'pseudoconstant' => array( + 'optionGroupName' => 'accept_creditcard', + 'optionEditPath' => 'civicrm/admin/options/accept_creditcard', + ) + ) , 'financial_trxn_check_number' => array( 'name' => 'check_number', 'type' => CRM_Utils_Type::T_STRING, @@ -385,6 +413,18 @@ class CRM_Financial_DAO_FinancialTrxn extends CRM_Core_DAO { 'type' => 'Text', ) , ) , + 'financial_trxn_pan_truncation' => array( + 'name' => 'pan_truncation', + 'type' => CRM_Utils_Type::T_INT, + 'title' => ts('Pan Truncation') , + 'description' => 'Last 4 digits of credit card', + 'table_name' => 'civicrm_financial_trxn', + 'entity' => 'FinancialTrxn', + 'bao' => 'CRM_Financial_DAO_FinancialTrxn', + 'html' => array( + 'type' => 'Text', + ) , + ) , ); CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']); } diff --git a/civicrm/CRM/Group/Page/Group.php b/civicrm/CRM/Group/Page/Group.php index da6e8eec70d0242549cd17c753e2664d8f4c1a0c..d78bec5cfcee69fc29ec022a0fc905a078368c91 100644 --- a/civicrm/CRM/Group/Page/Group.php +++ b/civicrm/CRM/Group/Page/Group.php @@ -99,21 +99,6 @@ class CRM_Group_Page_Group extends CRM_Core_Page_Basic { return 'reset=1&action=browse'; } - /** - * Make sure that the user has permission to access this group. - * - * @param int $id - * The id of the object. - * @param int $title - * Name or title of the object. - * - * @return string - * the permission that the user has (or null) - */ - public function checkPermission($id, $title) { - return CRM_Contact_BAO_Group::checkPermission($id, $title); - } - /** * Re-implement browse. * diff --git a/civicrm/CRM/Logging/Reverter.php b/civicrm/CRM/Logging/Reverter.php index 7d838dc641d251bb2a30a4befbf60febac5bb987..4e9310ff03ed9452e2503b63277b0fa829aece49 100644 --- a/civicrm/CRM/Logging/Reverter.php +++ b/civicrm/CRM/Logging/Reverter.php @@ -200,32 +200,6 @@ class CRM_Logging_Reverter { } } - // CRM-7353: if nothing altered civicrm_contact, touch it; this will - // make sure there’s an entry in log_civicrm_contact for this revert - if (empty($diffs['civicrm_contact'])) { - $query = " - SELECT id FROM `{$this->db}`.log_civicrm_contact - WHERE log_conn_id = %1 AND log_date BETWEEN DATE_SUB(%2, INTERVAL 10 SECOND) AND DATE_ADD(%2, INTERVAL 10 SECOND) - ORDER BY log_date DESC LIMIT 1 - "; - $params = array( - 1 => array($this->log_conn_id, 'String'), - 2 => array($this->log_date, 'String'), - ); - $cid = CRM_Core_DAO::singleValueQuery($query, $params); - if (!$cid) { - return; - } - - $dao = new CRM_Contact_DAO_Contact(); - $dao->id = $cid; - if ($dao->find(TRUE)) { - // CRM-8102: MySQL can’t parse its own dates - $dao->birth_date = CRM_Utils_Date::isoToMysql($dao->birth_date); - $dao->deceased_date = CRM_Utils_Date::isoToMysql($dao->deceased_date); - $dao->save(); - } - } } } diff --git a/civicrm/CRM/Mailing/ActionTokens.php b/civicrm/CRM/Mailing/ActionTokens.php index 130b5cd1b2d151370ee8f964055f7776c0acb051..28158cbbe63227aa4e4f0bea956b01736c1262e1 100644 --- a/civicrm/CRM/Mailing/ActionTokens.php +++ b/civicrm/CRM/Mailing/ActionTokens.php @@ -61,6 +61,13 @@ class CRM_Mailing_ActionTokens extends \Civi\Token\AbstractTokenSubscriber { )); } + /** + * @inheritDoc + */ + public function checkActive(\Civi\Token\TokenProcessor $processor) { + return !empty($processor->context['mailingId']) || !empty($processor->context['mailing']); + } + /** * @inheritDoc */ diff --git a/civicrm/CRM/Mailing/BAO/Mailing.php b/civicrm/CRM/Mailing/BAO/Mailing.php index 80056cae312ba64c2f2b9273bff94ab6cf14fbd5..d746b5abc846259e7cc8eb2f397ed733fa9f457c 100644 --- a/civicrm/CRM/Mailing/BAO/Mailing.php +++ b/civicrm/CRM/Mailing/BAO/Mailing.php @@ -1093,6 +1093,10 @@ ORDER BY civicrm_email.is_bulkmail DESC $localpart = CRM_Core_BAO_MailSettings::defaultLocalpart(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); + // Make sure the user configured the site correctly, otherwise you just get "Could not identify any recipients. Perhaps the group is empty?" from the mailing UI + if (empty($emailDomain)) { + CRM_Core_Error::debug_log_message('Error setting verp parameters, defaultDomain is NULL. Did you configure the bounce processing account for this domain?'); + } foreach ($verpTokens as $key => $value) { $verp[$key] = implode($config->verpSeparator, diff --git a/civicrm/CRM/Mailing/Event/BAO/Bounce.php b/civicrm/CRM/Mailing/Event/BAO/Bounce.php index 612b1783afa464498437fd53f7d0e15f83146dba..ae9944f0b9eadb51aa63cf5a71063c71103d161c 100644 --- a/civicrm/CRM/Mailing/Event/BAO/Bounce.php +++ b/civicrm/CRM/Mailing/Event/BAO/Bounce.php @@ -46,8 +46,8 @@ class CRM_Mailing_Event_BAO_Bounce extends CRM_Mailing_Event_DAO_Bounce { * * @return bool|null */ - public static function &create(&$params) { - $q = &CRM_Mailing_Event_BAO_Queue::verify($params['job_id'], + public static function create(&$params) { + $q = CRM_Mailing_Event_BAO_Queue::verify($params['job_id'], $params['event_queue_id'], $params['hash'] ); @@ -79,45 +79,13 @@ class CRM_Mailing_Event_BAO_Bounce extends CRM_Mailing_Event_DAO_Bounce { $bounce->copyValues($params); $bounce->save(); - $success = TRUE; - $bounceTable = CRM_Mailing_Event_BAO_Bounce::getTableName(); - $bounceType = CRM_Mailing_DAO_BounceType::getTableName(); - $emailTable = CRM_Core_BAO_Email::getTableName(); - $queueTable = CRM_Mailing_Event_BAO_Queue::getTableName(); - - $bounce->reset(); - // might want to put distinct inside the count - $query = "SELECT count($bounceTable.id) as bounces, - $bounceType.hold_threshold as threshold - FROM $bounceTable - INNER JOIN $bounceType - ON $bounceTable.bounce_type_id = $bounceType.id - INNER JOIN $queueTable - ON $bounceTable.event_queue_id = $queueTable.id - INNER JOIN $emailTable - ON $queueTable.email_id = $emailTable.id - WHERE $emailTable.id = {$q->email_id} - AND ($emailTable.reset_date IS NULL - OR $bounceTable.time_stamp >= $emailTable.reset_date) - GROUP BY $bounceTable.bounce_type_id - ORDER BY threshold, bounces desc"; - - $bounce->query($query); - - while ($bounce->fetch()) { - if ($bounce->bounces >= $bounce->threshold) { - $email = new CRM_Core_BAO_Email(); - $email->id = $q->email_id; - $email->on_hold = TRUE; - $email->hold_date = date('YmdHis'); - $email->save(); - break; - } + if ($q->email_id) { + self::putEmailOnHold($q->email_id); } $transaction->commit(); - return $success; + return TRUE; } /** @@ -279,4 +247,46 @@ class CRM_Mailing_Event_BAO_Bounce extends CRM_Mailing_Event_DAO_Bounce { return $results; } + /** + * Put the email on hold if it has met the threshold. + * + * @param int $email_id + */ + protected static function putEmailOnHold($email_id) { + + $bounceTable = CRM_Mailing_Event_BAO_Bounce::getTableName(); + $bounceType = CRM_Mailing_DAO_BounceType::getTableName(); + $emailTable = CRM_Core_BAO_Email::getTableName(); + $queueTable = CRM_Mailing_Event_BAO_Queue::getTableName(); + + // might want to put distinct inside the count + $query = "SELECT count($bounceTable.id) as bounces, + $bounceType.hold_threshold as threshold + FROM $bounceTable + INNER JOIN $bounceType + ON $bounceTable.bounce_type_id = $bounceType.id + INNER JOIN $queueTable + ON $bounceTable.event_queue_id = $queueTable.id + INNER JOIN $emailTable + ON $queueTable.email_id = $emailTable.id + WHERE $emailTable.id = $email_id + AND ($emailTable.reset_date IS NULL + OR $bounceTable.time_stamp >= $emailTable.reset_date) + GROUP BY $bounceTable.bounce_type_id + ORDER BY threshold, bounces desc"; + + $dao = CRM_Core_DAO::executeQuery($query); + + while ($dao->fetch()) { + if ($dao->bounces >= $dao->threshold) { + $email = new CRM_Core_BAO_Email(); + $email->id = $email_id; + $email->on_hold = TRUE; + $email->hold_date = date('YmdHis'); + $email->save(); + break; + } + } + } + } diff --git a/civicrm/CRM/Mailing/Event/BAO/Unsubscribe.php b/civicrm/CRM/Mailing/Event/BAO/Unsubscribe.php index 461ba9bd78b6fe947339c365fc35e975ad62efbb..01ab5a1751242ca2a820cadafdb7a9c08c014b97 100644 --- a/civicrm/CRM/Mailing/Event/BAO/Unsubscribe.php +++ b/civicrm/CRM/Mailing/Event/BAO/Unsubscribe.php @@ -216,21 +216,23 @@ WHERE email = %2 } //Pass the groups to be unsubscribed from through a hook. - $group_ids = array_keys($groups); - $base_group_ids = array_keys($base_groups); - CRM_Utils_Hook::unsubscribeGroups('unsubscribe', $mailing_id, $contact_id, $group_ids, $base_group_ids); + $groupIds = array_keys($groups); + //include child groups if any + $groupIds = array_merge($groupIds, CRM_Contact_BAO_Group::getChildGroupIds($groupIds)); + + $baseGroupIds = array_keys($base_groups); + CRM_Utils_Hook::unsubscribeGroups('unsubscribe', $mailing_id, $contact_id, $groupIds, $baseGroupIds); // Now we have a complete list of recipient groups. Filter out all // those except smart groups, those that the contact belongs to and // base groups from search based mailings. - $baseGroupClause = ''; - if (!empty($base_group_ids)) { - $baseGroupClause = "OR $group.id IN(" . implode(', ', $base_group_ids) . ")"; + if (!empty($baseGroupIds)) { + $baseGroupClause = "OR $group.id IN(" . implode(', ', $baseGroupIds) . ")"; } $groupIdClause = ''; - if ($group_ids || $base_group_ids) { - $groupIdClause = "AND $group.id IN (" . implode(', ', array_merge($group_ids, $base_group_ids)) . ")"; + if ($groupIds || $baseGroupIds) { + $groupIdClause = "AND $group.id IN (" . implode(', ', array_merge($groupIds, $baseGroupIds)) . ")"; } $do->query(" SELECT $group.id as group_id, @@ -267,7 +269,7 @@ WHERE email = %2 foreach ($groups as $group_id => $group_name) { $notremoved = FALSE; if ($group_name) { - if (in_array($group_id, $base_group_ids)) { + if (in_array($group_id, $baseGroupIds)) { list($total, $removed, $notremoved) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contacts, $group_id, 'Email', 'Removed'); } else { diff --git a/civicrm/CRM/Member/DAO/Membership.php b/civicrm/CRM/Member/DAO/Membership.php index 45a038c72483b4776b907767b72b0ea3a3dffbd8..a3cb6c7097ca63a00c76336e22a9e2412e51ffc1 100644 --- a/civicrm/CRM/Member/DAO/Membership.php +++ b/civicrm/CRM/Member/DAO/Membership.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Member/Membership.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:794bd904da5edcacc20dd5784fcdcf0c) + * (GenCodeChecksum:d92ffd88f95da56ec5e4463369c59155) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -244,7 +244,7 @@ class CRM_Member_DAO_Membership extends CRM_Core_DAO { 'bao' => 'CRM_Member_BAO_Membership', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDate', + 'formatType' => 'activityDate', ) , ) , 'membership_start_date' => array( @@ -262,7 +262,7 @@ class CRM_Member_DAO_Membership extends CRM_Core_DAO { 'bao' => 'CRM_Member_BAO_Membership', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDate', + 'formatType' => 'activityDate', ) , ) , 'membership_end_date' => array( @@ -280,7 +280,7 @@ class CRM_Member_DAO_Membership extends CRM_Core_DAO { 'bao' => 'CRM_Member_BAO_Membership', 'html' => array( 'type' => 'Select Date', - 'format' => 'activityDate', + 'formatType' => 'activityDate', ) , ) , 'membership_source' => array( diff --git a/civicrm/CRM/Price/BAO/LineItem.php b/civicrm/CRM/Price/BAO/LineItem.php index 4767d5e7ff80f23f855a3214cd01c3990e5ca266..56694bd71cf66b949962fe869760d1f85d14fe6d 100644 --- a/civicrm/CRM/Price/BAO/LineItem.php +++ b/civicrm/CRM/Price/BAO/LineItem.php @@ -298,7 +298,15 @@ WHERE li.contribution_id = %1"; 'tax_amount' => $dao->tax_amount, 'price_set_id' => $dao->price_set_id, ); - $lineItems[$dao->id]['tax_rate'] = CRM_Price_BAO_LineItem::calculateTaxRate($lineItems[$dao->id]); + $taxRates = CRM_Core_PseudoConstant::getTaxRates(); + if (isset($lineItems[$dao->id]['financial_type_id']) && array_key_exists($lineItems[$dao->id]['financial_type_id'], $taxRates)) { + // We are close to output/display here - so apply some rounding at output/display level - to not show Tax Rate in all 8 decimals + $lineItems[$dao->id]['tax_rate'] = round($taxRates[$lineItems[$dao->id]['financial_type_id']], 3); + } + else { + // There is no Tax Rate associated with this Financial Type + $lineItems[$dao->id]['tax_rate'] = FALSE; + } $lineItems[$dao->id]['subTotal'] = $lineItems[$dao->id]['qty'] * $lineItems[$dao->id]['unit_price']; if ($lineItems[$dao->id]['tax_amount'] != '') { $getTaxDetails = TRUE; @@ -597,26 +605,4 @@ WHERE li.contribution_id = %1"; } } - /** - * Calculate tax rate in percentage. - * - * @param array $lineItemId - * An assoc array of lineItem. - * - * @return int|void - * tax rate - */ - public static function calculateTaxRate($lineItemId) { - if ($lineItemId['unit_price'] == 0 || $lineItemId['qty'] == 0) { - return FALSE; - } - if ($lineItemId['html_type'] == 'Text') { - $tax = round($lineItemId['tax_amount'] / ($lineItemId['unit_price'] * $lineItemId['qty']) * 100, 2); - } - else { - $tax = round(($lineItemId['tax_amount'] / $lineItemId['unit_price']) * 100, 2); - } - return $tax; - } - } diff --git a/civicrm/CRM/Price/BAO/PriceField.php b/civicrm/CRM/Price/BAO/PriceField.php index 5b56b2eeaabb0139e688a468af1d426cdaafd9f4..6f3284c63be79936f48fdfdf67b1f610da2fd800 100644 --- a/civicrm/CRM/Price/BAO/PriceField.php +++ b/civicrm/CRM/Price/BAO/PriceField.php @@ -143,6 +143,7 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { if ($options['membership_type_id']) { $options['membership_num_terms'] = CRM_Utils_Array::value($index, CRM_Utils_Array::value('membership_num_terms', $params), 1); + $options['is_default'] = CRM_Utils_Array::value($params['membership_type_id'][$index], $defaultArray) ? $defaultArray[$params['membership_type_id'][$index]] : 0; } if (CRM_Utils_Array::value($index, CRM_Utils_Array::value('option_financial_type_id', $params))) { diff --git a/civicrm/CRM/Price/BAO/PriceFieldValue.php b/civicrm/CRM/Price/BAO/PriceFieldValue.php index b02b7cb4ce08144d7c9b6f69885e7a98f5ba33dd..2f337386d5ced906b00ba6f97c330828c05e530c 100644 --- a/civicrm/CRM/Price/BAO/PriceFieldValue.php +++ b/civicrm/CRM/Price/BAO/PriceFieldValue.php @@ -29,8 +29,6 @@ * * @package CRM * @copyright CiviCRM LLC (c) 2004-2017 - * $Id$ - * */ /** @@ -43,9 +41,9 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue { * Insert/update a new entry in the database. * * @param array $params - * (reference), array $ids. * - * @param $ids + * @param array $ids + * Deprecated variable. * * @return CRM_Price_DAO_PriceFieldValue */ @@ -157,7 +155,7 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue { } /** - * Retrive the all values for given field id. + * Retrieve all values for given field id. * * @param int $fieldId * Price_field_id. diff --git a/civicrm/CRM/Price/BAO/PriceSet.php b/civicrm/CRM/Price/BAO/PriceSet.php index 39fa2d567cf8796593bfd43ab6b53b3301691ba1..af7518f3ecc19758c3f645ef7f5604b9b38129a7 100644 --- a/civicrm/CRM/Price/BAO/PriceSet.php +++ b/civicrm/CRM/Price/BAO/PriceSet.php @@ -29,12 +29,10 @@ * * @package CRM * @copyright CiviCRM LLC (c) 2004-2017 - * $Id$ - * */ /** - * Business object for managing price sets + * Business object for managing price sets. * */ class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet { @@ -191,23 +189,17 @@ WHERE ps.name = '{$entityName}' * * @return array */ - public static function &getUsedBy($id, $simpleReturn = FALSE) { - $usedBy = $forms = $tables = array(); - $queryString = " -SELECT entity_table, entity_id -FROM civicrm_price_set_entity -WHERE price_set_id = %1"; - $params = array(1 => array($id, 'Integer')); - $crmFormDAO = CRM_Core_DAO::executeQuery($queryString, $params); - - while ($crmFormDAO->fetch()) { - $forms[$crmFormDAO->entity_table][] = $crmFormDAO->entity_id; - $tables[] = $crmFormDAO->entity_table; - } - // Return only tables + public static function getUsedBy($id, $simpleReturn = FALSE) { + $usedBy = array(); + $forms = self::getFormsUsingPriceSet($id); + $tables = array_keys($forms); + // @todo - this is really clumsy overloading the signature like this. Instead + // move towards having a function that does not call reformatUsedByFormsWithEntityData + // and call that when that data is not used. if ($simpleReturn == 'table') { return $tables; } + // @todo - this is painfully slow in some cases. if (empty($forms)) { $queryString = " SELECT cli.entity_table, cli.entity_id @@ -224,74 +216,17 @@ WHERE cpf.price_set_id = %1"; return $usedBy; } } - // Return only entity data + // @todo - this is really clumsy overloading the signature like this. See above. if ($simpleReturn == 'entity') { return $forms; } - foreach ($forms as $table => $entities) { - switch ($table) { - case 'civicrm_event': - $ids = implode(',', $entities); - $queryString = "SELECT ce.id as id, ce.title as title, ce.is_public as isPublic, ce.start_date as startDate, ce.end_date as endDate, civicrm_option_value.label as eventType, ce.is_template as isTemplate, ce.template_title as templateTitle -FROM civicrm_event ce -LEFT JOIN civicrm_option_value ON - ( ce.event_type_id = civicrm_option_value.value ) -LEFT JOIN civicrm_option_group ON - ( civicrm_option_group.id = civicrm_option_value.option_group_id ) -WHERE - civicrm_option_group.name = 'event_type' AND - ce.id IN ($ids) AND - ce.is_active = 1;"; - $crmDAO = CRM_Core_DAO::executeQuery($queryString); - while ($crmDAO->fetch()) { - if ($crmDAO->isTemplate) { - $usedBy['civicrm_event_template'][$crmDAO->id]['title'] = $crmDAO->templateTitle; - $usedBy['civicrm_event_template'][$crmDAO->id]['eventType'] = $crmDAO->eventType; - $usedBy['civicrm_event_template'][$crmDAO->id]['isPublic'] = $crmDAO->isPublic; - } - else { - $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title; - $usedBy[$table][$crmDAO->id]['eventType'] = $crmDAO->eventType; - $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate; - $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate; - $usedBy[$table][$crmDAO->id]['isPublic'] = $crmDAO->isPublic; - } - } - break; - - case 'civicrm_contribution_page': - $ids = implode(',', $entities); - $queryString = "SELECT cp.id as id, cp.title as title, cp.start_date as startDate, cp.end_date as endDate,ct.name as type -FROM civicrm_contribution_page cp, civicrm_financial_type ct -WHERE ct.id = cp.financial_type_id AND - cp.id IN ($ids) AND - cp.is_active = 1;"; - $crmDAO = CRM_Core_DAO::executeQuery($queryString); - while ($crmDAO->fetch()) { - $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title; - $usedBy[$table][$crmDAO->id]['type'] = $crmDAO->type; - $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate; - $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate; - } - break; - - case 'civicrm_contribution': - case 'civicrm_membership': - case 'civicrm_participant': - $usedBy[$table] = 1; - break; - - default: - CRM_Core_Error::fatal("$table is not supported in PriceSet::usedBy()"); - break; - } - } + $usedBy = self::reformatUsedByFormsWithEntityData($forms, $usedBy); return $usedBy; } /** - * Delete the price set. + * Delete the price set, including the fields. * * @param int $id * Price Set id. @@ -302,19 +237,6 @@ WHERE ct.id = cp.financial_type_id AND * */ public static function deleteSet($id) { - // remove from all inactive forms - $usedBy = self::getUsedBy($id); - if (isset($usedBy['civicrm_event'])) { - foreach ($usedBy['civicrm_event'] as $eventId => $unused) { - $eventDAO = new CRM_Event_DAO_Event(); - $eventDAO->id = $eventId; - $eventDAO->find(); - while ($eventDAO->fetch()) { - self::removeFrom('civicrm_event', $eventDAO->id); - } - } - } - // delete price fields $priceField = new CRM_Price_DAO_PriceField(); $priceField->price_set_id = $id; @@ -374,7 +296,7 @@ WHERE ct.id = cp.financial_type_id AND } /** - * Find a price_set_id associatied with the given table, id and usedFor + * Find a price_set_id associated with the given table, id and usedFor * Used For value for events:1, contribution:2, membership:3 * * @param string $entityTable @@ -549,17 +471,18 @@ WHERE ct.id = cp.financial_type_id AND $select = 'SELECT ' . implode(',', $priceFields); $from = ' FROM civicrm_price_field'; - $params = array(); - $params[1] = array($setID, 'Integer'); - $where = ' + $params = array( + 1 => array($setID, 'Integer'), + ); + $currentTime = date('YmdHis'); + $where = " WHERE price_set_id = %1 AND is_active = 1 -'; +AND ( active_on IS NULL OR active_on <= {$currentTime} ) +"; $dateSelect = ''; if ($validOnly) { - $currentTime = date('YmdHis'); $dateSelect = " -AND ( active_on IS NULL OR active_on <= {$currentTime} ) AND ( expire_on IS NULL OR expire_on >= {$currentTime} ) "; } @@ -624,7 +547,7 @@ WHERE id = %1"; */ public static function getOnlyPriceFieldID(array $priceSet) { if (count($priceSet['fields']) > 1) { - throw new CRM_Core_Exception(ts('expected only one price field to be in priceset but multiple are present')); + throw new CRM_Core_Exception(ts('expected only one price field to be in price set but multiple are present')); } return (int) implode('_', array_keys($priceSet['fields'])); } @@ -640,7 +563,7 @@ WHERE id = %1"; public static function getOnlyPriceFieldValueID(array $priceSet) { $priceFieldID = self::getOnlyPriceFieldID($priceSet); if (count($priceSet['fields'][$priceFieldID]['options']) > 1) { - throw new CRM_Core_Exception(ts('expected only one price field to be in priceset but multiple are present')); + throw new CRM_Core_Exception(ts('expected only one price field to be in price set but multiple are present')); } return (int) implode('_', array_keys($priceSet['fields'][$priceFieldID]['options'])); } @@ -666,7 +589,7 @@ WHERE id = %1"; $priceSetId = self::getFor($entityTable, $id); } - //check if priceset is is_config + //check if price set is is_config if (is_numeric($priceSetId)) { if (CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config') && $form->getVar('_name') != 'Participant') { $form->assign('quickConfig', 1); @@ -714,16 +637,16 @@ WHERE id = %1"; //get option count info. $form->_priceSet['optionsCountTotal'] = self::getPricesetCount($priceSetId); if ($form->_priceSet['optionsCountTotal']) { - $optionsCountDeails = array(); + $optionsCountDetails = array(); if (!empty($form->_priceSet['fields'])) { foreach ($form->_priceSet['fields'] as $field) { foreach ($field['options'] as $option) { $count = CRM_Utils_Array::value('count', $option, 0); - $optionsCountDeails['fields'][$field['id']]['options'][$option['id']] = $count; + $optionsCountDetails['fields'][$field['id']]['options'][$option['id']] = $count; } } } - $form->_priceSet['optionsCountDetails'] = $optionsCountDeails; + $form->_priceSet['optionsCountDetails'] = $optionsCountDetails; } //get option max value info. @@ -769,6 +692,7 @@ WHERE id = %1"; * @param string $component * This parameter appears to only be relevant to determining whether memberships should be auto-renewed. * (and is effectively a boolean for 'is_membership' which could be calculated from the line items.) + * @param int $priceSetID */ public static function processAmount($fields, &$params, &$lineItem, $component = '', $priceSetID = NULL) { // using price set @@ -1190,7 +1114,7 @@ WHERE id = %1"; return $defaults; } - foreach ($form->_priceSet['fields'] as $key => $val) { + foreach ($form->_priceSet['fields'] as $val) { foreach ($val['options'] as $keys => $values) { // build price field index which is passed via URL // url format will be appended by "&price_5=11" @@ -1666,11 +1590,12 @@ WHERE ps.id = %1 * @return array */ public static function setLineItem($field, $lineItem, $optionValueId, &$totalTax) { + // Here we round - i.e. after multiplying by quantity if ($field['html_type'] == 'Text') { - $taxAmount = $field['options'][$optionValueId]['tax_amount'] * $lineItem[$optionValueId]['qty']; + $taxAmount = round($field['options'][$optionValueId]['tax_amount'] * $lineItem[$optionValueId]['qty'], 2); } else { - $taxAmount = $field['options'][$optionValueId]['tax_amount']; + $taxAmount = round($field['options'][$optionValueId]['tax_amount'], 2); } $taxRate = $field['options'][$optionValueId]['tax_rate']; $lineItem[$optionValueId]['tax_amount'] = $taxAmount; @@ -1744,7 +1669,7 @@ WHERE ps.id = %1 public static function getNonDeductibleAmountFromPriceSet($priceSetId, $lineItem) { $nonDeductibleAmount = 0; if (!empty($lineItem[$priceSetId])) { - foreach ($lineItem[$priceSetId] as $fieldId => $options) { + foreach ($lineItem[$priceSetId] as $options) { $nonDeductibleAmount += $options['non_deductible_amount'] * $options['qty']; } } @@ -1752,4 +1677,111 @@ WHERE ps.id = %1 return $nonDeductibleAmount; } + /** + * Get an array of all forms using a given price set. + * + * @param int $id + * + * @return array + * Pages using the price set, keyed by type. e.g + * array(' + * 'civicrm_contribution_page' => array(2,5,6), + * 'civicrm_event' => array(5,6), + * 'civicrm_event_template' => array(7), + * ) + */ + public static function getFormsUsingPriceSet($id) { + $forms = array(); + $queryString = " +SELECT entity_table, entity_id +FROM civicrm_price_set_entity +WHERE price_set_id = %1"; + $params = array(1 => array($id, 'Integer')); + $crmFormDAO = CRM_Core_DAO::executeQuery($queryString, $params); + + while ($crmFormDAO->fetch()) { + $forms[$crmFormDAO->entity_table][] = $crmFormDAO->entity_id; + } + return $forms; + } + + /** + * @param array $forms + * Array of forms that use a price set keyed by entity. e.g + * array(' + * 'civicrm_contribution_page' => array(2,5,6), + * 'civicrm_event' => array(5,6), + * 'civicrm_event_template' => array(7), + * ) + * + * @return mixed + * Array of entities suppliemented with per entity information. + * e.g + * array('civicrm_event' => array(7 => array('title' => 'x'...)) + * + * @throws \Exception + */ + protected static function reformatUsedByFormsWithEntityData($forms) { + $usedBy = array(); + foreach ($forms as $table => $entities) { + switch ($table) { + case 'civicrm_event': + $ids = implode(',', $entities); + $queryString = "SELECT ce.id as id, ce.title as title, ce.is_public as isPublic, ce.start_date as startDate, ce.end_date as endDate, civicrm_option_value.label as eventType, ce.is_template as isTemplate, ce.template_title as templateTitle +FROM civicrm_event ce +LEFT JOIN civicrm_option_value ON + ( ce.event_type_id = civicrm_option_value.value ) +LEFT JOIN civicrm_option_group ON + ( civicrm_option_group.id = civicrm_option_value.option_group_id ) +WHERE + civicrm_option_group.name = 'event_type' AND + ce.id IN ($ids) AND + ce.is_active = 1;"; + $crmDAO = CRM_Core_DAO::executeQuery($queryString); + while ($crmDAO->fetch()) { + if ($crmDAO->isTemplate) { + $usedBy['civicrm_event_template'][$crmDAO->id]['title'] = $crmDAO->templateTitle; + $usedBy['civicrm_event_template'][$crmDAO->id]['eventType'] = $crmDAO->eventType; + $usedBy['civicrm_event_template'][$crmDAO->id]['isPublic'] = $crmDAO->isPublic; + } + else { + $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title; + $usedBy[$table][$crmDAO->id]['eventType'] = $crmDAO->eventType; + $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate; + $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate; + $usedBy[$table][$crmDAO->id]['isPublic'] = $crmDAO->isPublic; + } + } + break; + + case 'civicrm_contribution_page': + $ids = implode(',', $entities); + $queryString = "SELECT cp.id as id, cp.title as title, cp.start_date as startDate, cp.end_date as endDate,ct.name as type +FROM civicrm_contribution_page cp, civicrm_financial_type ct +WHERE ct.id = cp.financial_type_id AND + cp.id IN ($ids) AND + cp.is_active = 1;"; + $crmDAO = CRM_Core_DAO::executeQuery($queryString); + while ($crmDAO->fetch()) { + $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title; + $usedBy[$table][$crmDAO->id]['type'] = $crmDAO->type; + $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate; + $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate; + } + break; + + case 'civicrm_contribution': + case 'civicrm_membership': + case 'civicrm_participant': + $usedBy[$table] = 1; + break; + + default: + CRM_Core_Error::fatal("$table is not supported in PriceSet::usedBy()"); + break; + } + } + return $usedBy; + } + } diff --git a/civicrm/CRM/Price/Form/DeleteSet.php b/civicrm/CRM/Price/Form/DeleteSet.php index 7adc42f22d5f32f959dda162bf3956d3e680f47e..a4bb5a0d8a33870fe157aa9608b1981a4a0fbc3f 100644 --- a/civicrm/CRM/Price/Form/DeleteSet.php +++ b/civicrm/CRM/Price/Form/DeleteSet.php @@ -29,8 +29,6 @@ * * @package CRM * @copyright CiviCRM LLC (c) 2004-2017 - * $Id$ - * */ /** diff --git a/civicrm/CRM/Price/Form/Field.php b/civicrm/CRM/Price/Form/Field.php index bf39aa55b78e9cc565e695a04c95ee9500461ac4..51f7d3fd053f100b0b02e63e3b01334a8595fcf8 100644 --- a/civicrm/CRM/Price/Form/Field.php +++ b/civicrm/CRM/Price/Form/Field.php @@ -327,13 +327,6 @@ class CRM_Price_Form_Field extends CRM_Core_Form { CRM_Core_DAO::getAttribute('CRM_Price_DAO_PriceField', 'help_post') ); - // active_on - $date_options = array( - 'format' => 'dmY His', - 'minYear' => date('Y') - 1, - 'maxYear' => date('Y') + 5, - 'addEmptyOption' => TRUE, - ); $this->addDateTime('active_on', ts('Active On'), FALSE, array('formatType' => 'activityDateTime')); // expire_on diff --git a/civicrm/CRM/Price/Form/Option.php b/civicrm/CRM/Price/Form/Option.php index 477ec36c9b62d53e08a1d62631c828a2bfb33564..99126381c8a9b963b46c9e267d6bbb88c7a7473e 100644 --- a/civicrm/CRM/Price/Form/Option.php +++ b/civicrm/CRM/Price/Form/Option.php @@ -115,8 +115,7 @@ class CRM_Price_Form_Option extends CRM_Core_Form { public function buildQuickForm() { if ($this->_action == CRM_Core_Action::UPDATE) { $finTypeId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $this->_oid, 'financial_type_id'); - CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialTypes, CRM_Core_Action::UPDATE); - if (!array_key_exists($finTypeId, $financialTypes)) { + if (!CRM_Financial_BAO_FinancialType::checkPermissionToEditFinancialType($finTypeId)) { CRM_Core_Error::fatal(ts("You do not have permission to access this page")); } } diff --git a/civicrm/CRM/Price/Page/Option.php b/civicrm/CRM/Price/Page/Option.php index 2a7f82f35113289a9e259ade9e843e7ea1cb5ef3..5e3daafb184d9ca9425f5beeeb925264aff2e5b1 100644 --- a/civicrm/CRM/Price/Page/Option.php +++ b/civicrm/CRM/Price/Page/Option.php @@ -121,8 +121,13 @@ class CRM_Price_Page_Option extends CRM_Core_Page { * @return void */ public function browse() { - $customOption = array(); - CRM_Price_BAO_PriceFieldValue::getValues($this->_fid, $customOption); + $priceOptions = civicrm_api3('PriceFieldValue', 'get', array( + 'price_field_id' => $this->_fid, + // Explicitly do not check permissions so we are not + // restricted by financial type, so we can change them. + 'check_permissions' => FALSE, + )); + $customOption = $priceOptions['values']; // CRM-15378 - check if these price options are in an Event price set $isEvent = FALSE; @@ -134,7 +139,6 @@ class CRM_Price_Page_Option extends CRM_Core_Page { } $config = CRM_Core_Config::singleton(); - $financialType = CRM_Contribute_PseudoConstant::financialType(); $taxRate = CRM_Core_PseudoConstant::getTaxRates(); // display taxTerm for priceFields $invoiceSettings = Civi::settings()->get('contribution_invoice_settings'); @@ -153,7 +157,7 @@ class CRM_Price_Page_Option extends CRM_Core_Page { $customOption[$id]['tax_amount'] = $taxAmount['tax_amount']; } if (!empty($values['financial_type_id'])) { - $customOption[$id]['financial_type_id'] = $financialType[$values['financial_type_id']]; + $customOption[$id]['financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($values['financial_type_id']); } // update enable/disable links depending on price_field properties. if ($this->_isSetReserved) { diff --git a/civicrm/CRM/Price/Page/Set.php b/civicrm/CRM/Price/Page/Set.php index 1a54f366036de6166b10794cafb9edb6e872739a..c3ec481e7b5fa770b67423f50871ded3de843e0a 100644 --- a/civicrm/CRM/Price/Page/Set.php +++ b/civicrm/CRM/Price/Page/Set.php @@ -143,7 +143,6 @@ class CRM_Price_Page_Set extends CRM_Core_Page { $this->preview($sid); } elseif ($action & CRM_Core_Action::COPY) { - $session = CRM_Core_Session::singleton(); CRM_Core_Session::setStatus(ts('A copy of the price set has been created'), ts('Saved'), 'success'); $this->copy(); } @@ -155,10 +154,8 @@ class CRM_Price_Page_Set extends CRM_Core_Page { if (empty($usedBy)) { // prompt to delete - $session = CRM_Core_Session::singleton(); - $session->pushUserContext(CRM_Utils_System::url('civicrm/admin/price', 'action=browse')); + CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/admin/price', 'action=browse')); $controller = new CRM_Core_Controller_Simple('CRM_Price_Form_DeleteSet', 'Delete Price Set', NULL); - // $id = CRM_Utils_Request::retrieve('sid', 'Positive', $this, false, 0); $controller->set('sid', $sid); $controller->setEmbedded(TRUE); $controller->process(); diff --git a/civicrm/CRM/Profile/Form.php b/civicrm/CRM/Profile/Form.php index 9bcf0b9ee759e17a3d7d50f263ec3844a297c586..d6abda6e3d595cc9ddb84d4b9ea8ac271eda396b 100644 --- a/civicrm/CRM/Profile/Form.php +++ b/civicrm/CRM/Profile/Form.php @@ -500,7 +500,11 @@ class CRM_Profile_Form extends CRM_Core_Form { ) { $entityId = $this->_activityId; } - $url = CRM_Core_BAO_CustomField::getFileURL($entityId, $key); + + $url = ''; + if (isset($value)) { + $url = CRM_Core_BAO_CustomField::getFileURL($entityId, $key, $value); + } if ($url) { $customFiles[$name]['displayURL'] = ts("Attached File") . ": {$url['file_url']}"; diff --git a/civicrm/CRM/Report/Form.php b/civicrm/CRM/Report/Form.php index afb8857a4419f329fe10d01da52e2549d682d84e..5e1812e5f922160a299edc78f72794c50a3e845b 100644 --- a/civicrm/CRM/Report/Form.php +++ b/civicrm/CRM/Report/Form.php @@ -3433,6 +3433,9 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND if (!is_array($value)) { $value = array($value); } + //include child groups if any + $value = array_merge($value, CRM_Contact_BAO_Group::getChildGroupIds($value)); + $clause = "{$field['dbAlias']} IN (" . implode(', ', $value) . ")"; $contactAlias = $this->_aliases['civicrm_contact']; diff --git a/civicrm/CRM/Report/Form/Activity.php b/civicrm/CRM/Report/Form/Activity.php index 346d943b11b8d593557517797bed71b5a4160442..820b6f6d1e38a63ba701a2d5a2e2503c7671a2d5 100644 --- a/civicrm/CRM/Report/Form/Activity.php +++ b/civicrm/CRM/Report/Form/Activity.php @@ -283,6 +283,12 @@ class CRM_Report_Form_Activity extends CRM_Report_Form { 'title' => ts('Activity Details'), 'type' => CRM_Utils_Type::T_TEXT, ), + 'priority_id' => array( + 'title' => ts('Activity Priority'), + 'type' => CRM_Utils_Type::T_STRING, + 'operatorType' => CRM_Report_Form::OP_MULTISELECT, + 'options' => CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'), + ), ), 'order_bys' => array( 'activity_date_time' => array( @@ -882,6 +888,7 @@ FROM civireport_activity_temp_target tar $entryFound = FALSE; $activityType = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE); $activityStatus = CRM_Core_PseudoConstant::activityStatus(); + $priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'); $viewLinks = FALSE; $context = CRM_Utils_Request::retrieve('context', 'String', $this, FALSE, 'report'); $actUrl = ''; @@ -998,6 +1005,13 @@ FROM civireport_activity_temp_target tar } } + if (array_key_exists('civicrm_activity_priority_id', $row)) { + if ($value = $row['civicrm_activity_priority_id']) { + $rows[$rowNum]['civicrm_activity_priority_id'] = $priority[$value]; + $entryFound = TRUE; + } + } + if (array_key_exists('civicrm_activity_details', $row) && $this->_outputMode == 'html') { if ($value = $row['civicrm_activity_details']) { $fullDetails = $rows[$rowNum]['civicrm_activity_details']; diff --git a/civicrm/CRM/Report/Form/ActivitySummary.php b/civicrm/CRM/Report/Form/ActivitySummary.php index e1a1049a90777b522a4579026fd9ecf26098ea57..c8978ec05c02adcb650c4a8c11c2627c611e78dd 100644 --- a/civicrm/CRM/Report/Form/ActivitySummary.php +++ b/civicrm/CRM/Report/Form/ActivitySummary.php @@ -155,7 +155,7 @@ class CRM_Report_Form_ActivitySummary extends CRM_Report_Form { 'options' => CRM_Core_PseudoConstant::activityStatus(), ), 'priority_id' => array( - 'title' => ts('Priority'), + 'title' => ts('Activity Priority'), 'type' => CRM_Utils_Type::T_INT, 'operatorType' => CRM_Report_Form::OP_MULTISELECT, 'options' => CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'), @@ -251,7 +251,7 @@ class CRM_Report_Form_ActivitySummary extends CRM_Report_Form { if (array_key_exists('fields', $table)) { foreach ($table['fields'] as $fieldName => $field) { if (!empty($field['required']) || !empty($this->_params['fields'][$fieldName])) { - if ($tableName == 'civicrm_email') { + if ($tableName == 'civicrm_email' || in_array('email', CRM_Utils_Array::collect('column', $this->_params['order_bys']))) { $this->_emailField = TRUE; } if ($tableName == 'civicrm_phone') { @@ -337,13 +337,6 @@ class CRM_Report_Form_ActivitySummary extends CRM_Report_Form { LEFT JOIN civicrm_case_contact ON civicrm_case_contact.case_id = civicrm_case.id "; - if ($this->_emailField) { - $this->_from .= " - LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} - ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND - {$this->_aliases['civicrm_email']}.is_primary = 1 "; - } - if ($this->_phoneField) { $this->_from .= " LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']} @@ -361,6 +354,13 @@ class CRM_Report_Form_ActivitySummary extends CRM_Report_Form { ON target_activity.contact_id = contact_civireport.id {$this->_aclFrom}"; } + + if ($this->_emailField) { + $this->_from .= " + LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} + ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND + {$this->_aliases['civicrm_email']}.is_primary = 1 "; + } } /** diff --git a/civicrm/CRM/Report/Form/Contribute/Summary.php b/civicrm/CRM/Report/Form/Contribute/Summary.php index 684032ad1f72cd62c50be9ef47f840434e35b067..9b59afb436717bb07cc3295e7f8be4ef7b3e0ef0 100644 --- a/civicrm/CRM/Report/Form/Contribute/Summary.php +++ b/civicrm/CRM/Report/Form/Contribute/Summary.php @@ -229,6 +229,12 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form { 'civicrm_batch' => array( 'dao' => 'CRM_Batch_DAO_EntityBatch', 'grouping' => 'contri-fields', + 'fields' => array( + 'batch_id' => array( + 'name' => 'batch_id', + 'title' => ts('Batch Title'), + ), + ), 'filters' => array( 'batch_id' => array( 'title' => ts('Batch Title'), @@ -237,6 +243,9 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form { 'type' => CRM_Utils_Type::T_INT, ), ), + 'group_bys' => array( + 'batch_id' => array('title' => ts('Batch ID')), + ), ), 'civicrm_contribution_soft' => array( 'dao' => 'CRM_Contribute_DAO_ContributionSoft', @@ -495,14 +504,15 @@ class CRM_Report_Form_Contribute_Summary extends CRM_Report_Form { {$this->_aliases['civicrm_phone']}.is_primary = 1)"; $this->addAddressFromClause(); - if (!empty($this->_params['batch_id_value'])) { + //for contribution batches + if ($this->isTableSelected('civicrm_batch')) { $this->_from .= " - LEFT JOIN civicrm_entity_financial_trxn eft - ON eft.entity_id = {$this->_aliases['civicrm_contribution']}.id AND - eft.entity_table = 'civicrm_contribution' - LEFT JOIN civicrm_entity_batch {$this->_aliases['civicrm_batch']} - ON {$this->_aliases['civicrm_batch']}.entity_id = eft.financial_trxn_id AND - {$this->_aliases['civicrm_batch']}.entity_table = 'civicrm_financial_trxn'\n"; + LEFT JOIN civicrm_entity_financial_trxn eft + ON eft.entity_id = {$this->_aliases['civicrm_contribution']}.id AND + eft.entity_table = 'civicrm_contribution' + LEFT JOIN civicrm_entity_batch {$this->_aliases['civicrm_batch']} + ON ({$this->_aliases['civicrm_batch']}.entity_id = eft.financial_trxn_id + AND {$this->_aliases['civicrm_batch']}.entity_table = 'civicrm_financial_trxn')"; } } @@ -936,6 +946,12 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_ $entryFound = TRUE; } + // convert batch id to batch title + if (!empty($row['civicrm_batch_batch_id'])) { + $rows[$rowNum]['civicrm_batch_batch_id'] = CRM_Core_DAO::getFieldValue('CRM_Batch_BAO_Batch', $row['civicrm_batch_batch_id'], 'title'); + $entryFound = TRUE; + } + $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'contribute/detail', 'List all contribution(s) for this ') ? TRUE : $entryFound; $entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'contribute/detail', 'List all contribution(s) for this ') ? TRUE : $entryFound; diff --git a/civicrm/CRM/Report/Form/Event/Summary.php b/civicrm/CRM/Report/Form/Event/Summary.php index 9254f8bdcaab1c633d08f546680955819765600a..99a69328da3d0019e00865a80edb77035c8aae8f 100644 --- a/civicrm/CRM/Report/Form/Event/Summary.php +++ b/civicrm/CRM/Report/Form/Event/Summary.php @@ -202,8 +202,7 @@ class CRM_Report_Form_Event_Summary extends CRM_Report_Form_Event { $this->_participantWhere GROUP BY civicrm_participant.event_id, - civicrm_participant.status_id, - civicrm_participant.fee_currency"; + civicrm_participant.status_id"; $info = CRM_Core_DAO::executeQuery($sql); $participant_data = $participant_info = $currency = array(); @@ -262,8 +261,8 @@ class CRM_Report_Form_Event_Summary extends CRM_Report_Form_Event { } } - $statusType1 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1'); - $statusType2 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 0'); + $statusType1 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1', 'label'); + $statusType2 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 0', 'label'); //make column header for participant status Registered/Attended $type1_header = implode('/', $statusType1); diff --git a/civicrm/CRM/Tag/Form/Edit.php b/civicrm/CRM/Tag/Form/Edit.php index 6f7cc03d22b0fb1ce8d84bbe9f39b1a53111e15d..0919c7f07005656bdd88f236200d2573b34e4a9e 100644 --- a/civicrm/CRM/Tag/Form/Edit.php +++ b/civicrm/CRM/Tag/Form/Edit.php @@ -44,27 +44,44 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { return 'Tag'; } + public function preProcess() { + CRM_Utils_Request::retrieve('id', 'Integer', $this, FALSE); + $this->set('BAOName', 'CRM_Core_BAO_Tag'); + parent::preProcess(); + } + /** * Build the form object. */ public function buildQuickForm() { if ($this->_action == CRM_Core_Action::DELETE) { - if ($this->_id && $tag = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'name', 'parent_id')) { - $url = CRM_Utils_System::url('civicrm/tag', "reset=1"); - CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $url); + $url = CRM_Utils_System::url('civicrm/tag'); + if (!$this->_id) { + $this->_id = explode(',', CRM_Utils_Request::retrieve('id', 'String')); } - if ($this->_values['is_reserved'] == 1 && !CRM_Core_Permission::check('administer reserved tags')) { - CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag.")); + $this->_id = (array) $this->_id; + if (!$this->_id) { + CRM_Core_Error::statusBounce(ts("Unknown tag."), $url); + } + foreach ($this->_id as $id) { + if (!CRM_Utils_Rule::positiveInteger($id)) { + CRM_Core_Error::statusBounce(ts("Unknown tag."), $url); + } + if ($tag = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'name', 'parent_id')) { + CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $url); + } + if (!CRM_Core_Permission::check('administer reserved tags') && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'is_reserved')) { + CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag."), $url); + } + } + if (count($this->_id) > 1) { + $this->assign('delName', ts('%1 tags', array(1 => count($this->_id)))); } } else { - $parentId = NULL; - $isTagSetChild = FALSE; - $this->_isTagSet = CRM_Utils_Request::retrieve('tagset', 'Positive', $this); - if (!$this->_isTagSet && - $this->_id && + if (!$this->_isTagSet && $this->_id && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'is_tagset') ) { $this->_isTagSet = TRUE; @@ -72,8 +89,11 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { if ($this->_id) { $parentId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'parent_id'); - $isTagSetChild = $parentId ? CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $parentId, 'is_tagset') : FALSE; } + else { + $parentId = CRM_Utils_Request::retrieve('parent_id', 'Integer', $this); + } + $isTagSetChild = $parentId ? CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $parentId, 'is_tagset') : FALSE; if (!$this->_isTagSet) { if (!$isTagSetChild) { @@ -109,7 +129,9 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { $isReserved = $this->add('checkbox', 'is_reserved', ts('Reserved?')); - $this->addSelect('used_for', array('multiple' => TRUE, 'option_url' => NULL)); + if (!$isTagSetChild) { + $this->addSelect('used_for', array('multiple' => TRUE, 'option_url' => NULL)); + } $adminTagset = TRUE; if (!CRM_Core_Permission::check('administer Tagsets')) { @@ -135,10 +157,17 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { */ public function setDefaultValues() { $defaults = parent::setDefaultValues(); - if (empty($this->_id) || !CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'color')) { + $cloneFrom = CRM_Utils_Request::retrieve('clone_from', 'Integer'); + if (empty($this->_id) && $cloneFrom) { + $params = array('id' => $cloneFrom); + CRM_Core_BAO_Tag::retrieve($params, $this->_values); + $this->_values['name'] .= ' (' . ts('copy') . ')'; + $defaults = $this->_values; + } + if (empty($defaults['color'])) { $defaults['color'] = '#ffffff'; } - if (empty($this->_id)) { + if (empty($this->_id) && empty($defaults['used_for'])) { $defaults['used_for'] = 'civicrm_contact'; } return $defaults; @@ -148,46 +177,60 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { * Process the form submission. */ public function postProcess() { - // store the submitted values in an array - $params = $this->exportValues(); - if ($this->_id) { - $params['id'] = $this->_id; - } - - if ($this->_action == CRM_Core_Action::ADD || - $this->_action == CRM_Core_Action::UPDATE - ) { - $params['used_for'] = implode(",", $params['used_for']); + if ($this->_action == CRM_Core_Action::DELETE) { + $deleted = 0; + $tag = civicrm_api3('tag', 'getsingle', array('id' => $this->_id[0])); + foreach ($this->_id as $id) { + if (CRM_Core_BAO_Tag::del($id)) { + $deleted++; + } + } + if (count($this->_id) == 1 && $deleted == 1) { + if ($tag['is_tagset']) { + CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + } + else { + CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + } + } + else { + CRM_Core_Session::setStatus(ts("Deleted %1 tags.", array(1 => $deleted)), ts('Deleted'), 'success'); + } } + else { + $params = $this->exportValues(); + if ($this->_id) { + $params['id'] = $this->_id; + } - $params['is_tagset'] = 0; - if ($this->_isTagSet) { - $params['is_tagset'] = 1; - } + if (isset($params['used_for']) && ($this->_action == CRM_Core_Action::ADD || $this->_action == CRM_Core_Action::UPDATE)) { + $params['used_for'] = implode(",", $params['used_for']); + } - if (!isset($params['is_reserved'])) { - $params['is_reserved'] = 0; - } + $params['is_tagset'] = 0; + if ($this->_isTagSet) { + $params['is_tagset'] = 1; + } - if (!isset($params['is_selectable'])) { - $params['is_selectable'] = 0; - } + if (!isset($params['is_reserved'])) { + $params['is_reserved'] = 0; + } - if (strtolower($params['color']) == '#ffffff') { - $params['color'] = 'null'; - } + if (!isset($params['parent_id']) && $this->get('parent_id')) { + $params['parent_id'] = $this->get('parent_id'); + } + if (empty($params['parent_id'])) { + $params['parent_id'] = ''; + } - if ($this->_action == CRM_Core_Action::DELETE) { - if ($this->_id > 0) { - $tag = civicrm_api3('tag', 'getsingle', array('id' => $this->_id)); - CRM_Core_BAO_Tag::del($this->_id); - CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + if (!isset($params['is_selectable'])) { + $params['is_selectable'] = 0; } - } - else { $tag = CRM_Core_BAO_Tag::add($params); CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", array(1 => $tag->name)), ts('Saved'), 'success'); + $this->ajaxResponse['tag'] = $tag->toArray(); } + CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tag')); } } diff --git a/civicrm/CRM/Tag/Form/Merge.php b/civicrm/CRM/Tag/Form/Merge.php new file mode 100644 index 0000000000000000000000000000000000000000..f6778083d0b11d8ff84d9299db03f3778e58a978 --- /dev/null +++ b/civicrm/CRM/Tag/Form/Merge.php @@ -0,0 +1,126 @@ +<?php +/* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2017 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM 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 and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ + */ + +/** + * + * @package CRM + * @copyright CiviCRM LLC (c) 2004-2017 + */ + +/** + * Form for merging tags. + */ +class CRM_Tag_Form_Merge extends CRM_Core_Form { + protected $_id; + protected $_tags; + + public function preProcess() { + $this->_id = CRM_Utils_Request::retrieve('id', 'String', $this, FALSE); + $this->_id = explode(',', $this->_id); + $url = CRM_Utils_System::url('civicrm/tag'); + if (count($this->_id) < 2) { + CRM_Core_Error::statusBounce(ts("You must select at least 2 tags for merging."), $url); + } + $tags = civicrm_api3('Tag', 'get', array('id' => array('IN' => $this->_id), 'options' => array('limit' => 0))); + $this->_tags = $tags['values']; + if (count($this->_id) != count($this->_tags)) { + CRM_Core_Error::statusBounce(ts("Unknown tag."), $url); + } + if (!CRM_Core_Permission::check('administer reserved tags')) { + foreach ($tags['values'] as $tag) { + if (!empty($tag['is_reserved'])) { + CRM_Core_Error::statusBounce(ts("You do not have permission to administer reserved tags."), $url); + } + } + } + } + + /** + * Build the form object. + */ + public function buildQuickForm() { + $this->add('text', 'name', ts('Name of combined tag'), TRUE); + $this->assign('tags', CRM_Utils_Array::collect('name', $this->_tags)); + + $this->addButtons(array( + array( + 'type' => 'next', + 'name' => ts('Merge'), + 'spacing' => ' ', + 'isDefault' => TRUE, + ), + array( + 'type' => 'cancel', + 'name' => ts('Cancel'), + ), + ) + ); + } + + /** + * Set default values for the form. + * + * @return array + */ + public function setDefaultValues() { + $primary = CRM_Utils_Array::first($this->_tags); + return array( + 'name' => $primary['name'], + ); + } + + /** + * Process the form submission. + */ + public function postProcess() { + $params = $this->exportValues(); + $deleted = CRM_Utils_Array::collect('name', $this->_tags); + $primary = array_shift($this->_tags); + + foreach ($this->_tags as $tag) { + CRM_Core_BAO_EntityTag::mergeTags($primary['id'], $tag['id']); + } + + if ($params['name'] != $primary['name']) { + civicrm_api3('Tag', 'create', array('id' => $primary['id'], 'name' => $params['name'])); + } + + $key = array_search($params['name'], $deleted); + if ($key !== FALSE) { + unset($deleted[$key]); + } + + CRM_Core_Session::setStatus( + ts('All records previously tagged %1 are now tagged %2.', array(1 => implode(' ' . ts('or') . ' ', $deleted), 2 => $params['name'])), + ts('%1 Tags Merged', array(1 => count($this->_id))), + 'success' + ); + + CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tag')); + } + +} diff --git a/civicrm/CRM/Tag/Page/Tag.php b/civicrm/CRM/Tag/Page/Tag.php index 5a1c18259a9d4a27f571625c7f5fdd8a4ef34e8c..1c98beca046238513360a5109ce21cad26e40bf1 100644 --- a/civicrm/CRM/Tag/Page/Tag.php +++ b/civicrm/CRM/Tag/Page/Tag.php @@ -32,187 +32,48 @@ */ /** - * Page for displaying list of categories. + * Page for managing tags. */ -class CRM_Tag_Page_Tag extends CRM_Core_Page_Basic { - - public $useLivePageJS = TRUE; - - /** - * The action links that we need to display for the browse screen. - * - * @var array - */ - static $_links = NULL; - - /** - * Get BAO. - * - * @return string - * Classname of BAO. - */ - public function getBAOName() { - return 'CRM_Core_BAO_Tag'; - } - - /** - * Get action Links. - * - * @return array - * (reference) of action links - */ - public function &links() { - if (!(self::$_links)) { - self::$_links = array( - CRM_Core_Action::UPDATE => array( - 'name' => ts('Edit'), - 'url' => 'civicrm/tag', - 'qs' => 'action=update&id=%%id%%&reset=1', - 'title' => ts('Edit Tag'), - ), - CRM_Core_Action::DELETE => array( - 'name' => ts('Delete'), - 'url' => 'civicrm/tag', - 'qs' => 'action=delete&id=%%id%%', - 'title' => ts('Delete Tag'), - ), - CRM_Core_Action::FOLLOWUP => array( - 'name' => ts('Merge'), - 'class' => 'merge_tag', - 'title' => ts('Merge Tag'), - ), - ); - } - return self::$_links; - } - - /** - * Get name of edit form. - * - * @return string - * Classname of edit form. - */ - public function editForm() { - return 'CRM_Tag_Form_Edit'; - } - - /** - * Get form name for edit form. - * - * @return string - * name of this page. - */ - public function editName() { - return 'Tag'; - } - - /** - * Get form name for delete form. - * - * @return string - * name of this page. - */ - public function deleteName() { - return 'Tag'; - } - - /** - * Get user context. - * - * @param null $mode - * - * @return string - * user context. - */ - public function userContext($mode = NULL) { - return 'civicrm/tag'; - } - - /** - * Get name of delete form. - * - * @return string - * Classname of delete form. - */ - public function deleteForm() { - return 'CRM_Tag_Form_Edit'; - } +class CRM_Tag_Page_Tag extends CRM_Core_Page { /** - * Override function browse() - * - * @param null $action - * @param null $sort + * Run page */ - public function browse($action = NULL, $sort = NULL) { - $adminTagSet = FALSE; - if (CRM_Core_Permission::check('administer Tagsets')) { - $adminTagSet = TRUE; + public function run() { + CRM_Core_Resources::singleton() + ->addScriptFile('civicrm', 'bower_components/jstree/dist/jstree.min.js', 0, 'html-header') + ->addStyleFile('civicrm', 'bower_components/jstree/dist/themes/default/style.min.css') + ->addPermissions(array('administer reserved tags', 'administer Tagsets')); + + $usedFor = $tagsets = array(); + + $result = civicrm_api3('OptionValue', 'get', array( + 'return' => array("value", "name"), + 'option_group_id' => "tag_used_for", + )); + foreach ($result['values'] as $value) { + $usedFor[$value['value']] = $value['name']; } - $this->assign('adminTagSet', $adminTagSet); - - $reservedClause = !CRM_Core_Permission::check('administer reserved tags') ? "AND t1.is_reserved != 1" : ''; - $query = "SELECT t1.name, t1.id -FROM civicrm_tag t1 LEFT JOIN civicrm_tag t2 ON t1.id = t2.parent_id -WHERE t2.id IS NULL {$reservedClause}"; - $tag = CRM_Core_DAO::executeQuery($query); - - $mergeableTags = array(); - while ($tag->fetch()) { - $mergeableTags[$tag->id] = 1; - } - - $usedFor = CRM_Core_OptionGroup::values('tag_used_for'); - - $query = " SELECT t1.name, t1.id, t2.name as parent, t1.description, t1.used_for, t1.is_tagset as is_tagset, - t1.is_reserved, t1.parent_id, t1.used_for, t1.color, t2.is_tagset as is_tagset_child, t2.parent_id as grandparent_id - FROM civicrm_tag t1 - LEFT JOIN civicrm_tag t2 ON t1.parent_id = t2.id - LEFT JOIN civicrm_tag t3 ON t2.parent_id = t3.id - ORDER BY CONCAT(IFNULL(t3.name, ''), IFNULL(t2.name, ''), t1.name)"; - - $tag = CRM_Core_DAO::executeQuery($query); - $values = array(); - $action = CRM_Core_Action::UPDATE + CRM_Core_Action::DELETE; - $permission = CRM_Core_Permission::EDIT; - - while ($tag->fetch()) { - $values[$tag->id] = (array) $tag; - - $used = array(); - if ($values[$tag->id]['used_for']) { - $usedArray = explode(",", $values[$tag->id]['used_for']); - foreach ($usedArray as $key => $value) { - $used[$key] = $usedFor[$value]; - } - } - - $values[$tag->id]['used_for'] = implode(", ", $used); - - $newAction = $action; - if ($values[$tag->id]['is_reserved']) { - $newAction = CRM_Core_Action::UPDATE; - } - - if ($values[$tag->id]['is_tagset'] && !CRM_Core_Permission::check('administer Tagsets')) { - $newAction = 0; - } - - if (array_key_exists($tag->id, $mergeableTags)) { - $newAction += CRM_Core_Action::FOLLOWUP; - } - - // populate action links - if ($newAction) { - $this->action($tag, $newAction, $values[$tag->id], self::links(), $permission, TRUE); - } - else { - $values[$tag->id]['action'] = ''; + $result = civicrm_api3('Tag', 'get', array( + 'return' => array("name", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"), + 'is_tagset' => 1, + 'options' => array('limit' => 0), + )); + foreach ($result['values'] as $id => $tagset) { + $used = explode(',', CRM_Utils_Array::value('used_for', $tagset, '')); + $tagset['used_for_label'] = array_values(array_intersect_key($usedFor, array_flip($used))); + if (isset($tagset['created_id.display_name'])) { + $tagset['display_name'] = $tagset['created_id.display_name']; } + unset($tagset['created_id.display_name']); + $tagsets[$id] = $tagset; } - $this->assign('rows', $values); + $this->assign('usedFor', $usedFor); + $this->assign('tagsets', $tagsets); + + return parent::run(); } } diff --git a/civicrm/CRM/Upgrade/Incremental/php/FourSeven.php b/civicrm/CRM/Upgrade/Incremental/php/FourSeven.php index a1a3c58152a8edc27272882bd483cbd777a42d45..36b4313e9c95a4c081c5bb6e7b1eaabcd9cfc049 100644 --- a/civicrm/CRM/Upgrade/Incremental/php/FourSeven.php +++ b/civicrm/CRM/Upgrade/Incremental/php/FourSeven.php @@ -59,6 +59,9 @@ class CRM_Upgrade_Incremental_php_FourSeven extends CRM_Upgrade_Incremental_Base $preUpgradeMessage .= '<p>' . ts('The %1 payment processor is no longer bundled with CiviCRM. After upgrading you will need to install the extension to continue using it.', array(1 => 'Moneris')) . '</p>'; } } + if ($rev == '4.7.13') { + $preUpgradeMessage .= '<p>' . ts('A new permission has been added called %1 This Permission is now used to control access to the Manage Tags screen', array(1 => 'manage tags')) . '</p>'; + } } /** @@ -119,6 +122,7 @@ class CRM_Upgrade_Incremental_php_FourSeven extends CRM_Upgrade_Incremental_Base * @param string $rev */ public function upgrade_4_7_alpha1($rev) { + $this->addTask('Drop action scheudle mapping foreign key', 'dropActionScheudleMappingForeignKey'); $this->addTask('Migrate \'on behalf of\' information to module_data', 'migrateOnBehalfOfInfo'); $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev); $this->addTask(ts('Migrate Settings to %1', array(1 => $rev)), 'migrateSettings', $rev); @@ -780,6 +784,18 @@ FROM `civicrm_dashboard_contact` JOIN `civicrm_contact` WHERE civicrm_dashboard_ return TRUE; } + /** + * CRM-18464 Check if Foreign key exists and also drop any index of same name accidentially created. + * + * @param \CRM_Queue_TaskContext $ctx + * + * @return bool + */ + public static function dropActionScheudleMappingForeignKey(CRM_Queue_TaskContext $ctx) { + CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_action_schedule', 'FK_civicrm_action_schedule_mapping_id'); + return TRUE; + } + /** * CRM-18345 Don't delete mailing data on email/phone deletion * Implemented here in CRM-18526 diff --git a/civicrm/CRM/Upgrade/Incremental/sql/4.7.17.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/4.7.17.mysql.tpl new file mode 100644 index 0000000000000000000000000000000000000000..03a47793e26c73eb27ef722b6a2d98246ab9844f --- /dev/null +++ b/civicrm/CRM/Upgrade/Incremental/sql/4.7.17.mysql.tpl @@ -0,0 +1,14 @@ +{* file to handle db changes in 4.7.17 during upgrade *} + +-- CRM-19943 +UPDATE civicrm_navigation SET url = 'civicrm/tag' WHERE url = 'civicrm/tag?reset=1'; +UPDATE civicrm_navigation SET url = REPLACE(url, 'civicrm/tag', 'civicrm/tag/edit') WHERE url LIKE 'civicrm/tag?%'; + +-- CRM-19815, CRM-19830 update references to check_number to reflect unique name +UPDATE civicrm_uf_field SET field_name = 'contribution_check_number' WHERE field_name = 'check_number'; +UPDATE civicrm_mapping_field SET name = 'contribution_check_number' WHERE name = 'check_number'; + +-- CRM-20158 +ALTER TABLE `civicrm_financial_trxn` + ADD card_type INT( 10 ) UNSIGNED NULL DEFAULT NULL COMMENT 'FK to accept_creditcard option group values' AFTER payment_instrument_id, + ADD pan_truncation INT UNSIGNED NULL COMMENT 'Last 4 digits of credit card.' AFTER check_number; diff --git a/civicrm/CRM/Upgrade/Incremental/sql/4.7.alpha1.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/4.7.alpha1.mysql.tpl index 7ef1d6af18e2f8e651a06593c02629d0cc9baf57..df1ad7d5c76826743d194d361588ba90e8838457 100644 --- a/civicrm/CRM/Upgrade/Incremental/sql/4.7.alpha1.mysql.tpl +++ b/civicrm/CRM/Upgrade/Incremental/sql/4.7.alpha1.mysql.tpl @@ -3,7 +3,6 @@ -- Add new columns for multilingual purpose ALTER TABLE `civicrm_action_schedule` ADD COLUMN `filter_contact_language` varchar(128) DEFAULT NULL COMMENT 'Used for multilingual installation'; ALTER TABLE `civicrm_action_schedule` ADD COLUMN `communication_language` varchar(8) DEFAULT NULL COMMENT 'Used for multilingual installation'; -ALTER TABLE `civicrm_action_schedule` DROP FOREIGN KEY `FK_civicrm_action_schedule_mapping_id`; ALTER TABLE `civicrm_action_schedule` MODIFY COLUMN mapping_id varchar(64); -- Q: Should we validate that local civicrm_action_mapping records have expected IDs? diff --git a/civicrm/CRM/Utils/Check/Component/PriceFields.php b/civicrm/CRM/Utils/Check/Component/PriceFields.php new file mode 100644 index 0000000000000000000000000000000000000000..a36d9a5584272f1e213641989e296b4d63c8b34d --- /dev/null +++ b/civicrm/CRM/Utils/Check/Component/PriceFields.php @@ -0,0 +1,76 @@ +<?php + +/* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2016 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM 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 and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ + */ + +/** + * + * @package CRM + * @copyright CiviCRM LLC (c) 2004-2016 + */ +class CRM_Utils_Check_Component_PriceFields extends CRM_Utils_Check_Component { + + /** + * Display warning about invalid priceFields + * + */ + public function checkPriceFields() { + $sql = "SELECT DISTINCT ps.title as ps_title, ps.id as ps_id, psf.label as psf_label + FROM civicrm_price_set ps + INNER JOIN civicrm_price_field psf ON psf.price_set_id = ps.id + INNER JOIN civicrm_price_field_value pfv ON pfv.price_field_id = psf.id + LEFT JOIN civicrm_financial_type cft ON cft.id = pfv.financial_type_id + WHERE cft.id IS NULL OR cft.is_active = 0"; + $dao = CRM_Core_DAO::executeQuery($sql); + $count = 0; + $html = ''; + $messages = array(); + while ($dao->fetch()) { + $count++; + $url = CRM_Utils_System::url('civicrm/admin/price/field', array( + 'reset' => 1, + 'action' => 'browse', + 'sid' => $dao->ps_id)); + $html .= "<tr><td>$dao->ps_title</td><td>$dao->psf_label</td><td><a href='$url'>View Price Set Fields</a></td></tr>"; + } + if ($count > 0) { + $msg = "<p>the following Price Set Fields use disabled or invalid financial types and need to be fixed if they are to still be used.<p> + <p><table><thead><tr><th>Price Set</th><th>Price Set Field</th><th>Action Link</th> + </tr></thead><tbody> + $html + </tbody></table></p>"; + $messages[] = new CRM_Utils_Check_Message( + __FUNCTION__, + ts($msg), + ts('Invalid Price Fields'), + \Psr\Log\LogLevel::WARNING, + 'fa-lock' + ); + } + return $messages; + } + +} diff --git a/civicrm/CRM/Utils/Date.php b/civicrm/CRM/Utils/Date.php index 2f2a17d055b0ad9af5273abdf0a17c405783676a..3d8ed11f939a527e421dbc5f150a0a95c8d846e5 100644 --- a/civicrm/CRM/Utils/Date.php +++ b/civicrm/CRM/Utils/Date.php @@ -1741,6 +1741,108 @@ class CRM_Utils_Date { return $mysqlDate; } + /** + * Convert a Civi-special date string to a standard php date string. + * + * For historical reasons CiviCRM has it's own (possibly Smarty derived) + * format for defined date strings. This renders something php can use. + * + * @param string $dateFormatString + * e.g mm/dd/yy + * These map to the values used in the date_format field in civicrm_custom_field.date_format. + * + * @return string + * A proper php strotime formatted equivalent of the string. + * eg m/d/y for the above. + * + * http://php.net/manual/en/function.strtotime.php + */ + public static function getPhpDateFormatFromInputStyleDateFormat($dateFormatString) { + $formats = CRM_Core_SelectValues::datePluginToPHPFormats(); + return $formats[$dateFormatString]; + } + + /** + * Add the metadata about a date field to the field. + * + * This metadata will work with the call $form->add('datepicker', ... + * + * @param array $fieldMetaData + * @param array $field + * + * @return array + */ + public static function addDateMetadataToField($fieldMetaData, $field) { + if (isset($fieldMetaData['html'])) { + $field['html_type'] = $fieldMetaData['html']['type']; + if ($field['html_type'] === 'Select Date') { + if (!isset($field['date_format'])) { + $dateAttributes = CRM_Core_SelectValues::date($fieldMetaData['html']['formatType'], NULL, NULL, NULL, 'Input'); + $field['start_date_years'] = $dateAttributes['minYear']; + $field['end_date_years'] = $dateAttributes['maxYear']; + $field['date_format'] = $dateAttributes['format']; + $field['is_datetime_field'] = TRUE; + $field['time_format'] = $dateAttributes['time']; + $field['php_datetime_format'] = CRM_Utils_Date::getPhpDateFormatFromInputStyleDateFormat($field['date_format']); + if ($field['time_format']) { + $field['php_datetime_format'] .= ' H-i-s'; + } + } + $field['datepicker']['extra'] = self::getDatePickerExtra($field); + $field['datepicker']['attributes'] = self::getDatePickerAttributes($field); + } + } + return $field; + } + + + /** + * Get the fields required for the 'extra' parameter when adding a datepicker. + * + * @param array $field + * + * @return array + */ + public static function getDatePickerExtra($field) { + $extra = array(); + if (isset($field['date_format'])) { + $extra['date'] = $field['date_format']; + $extra['time'] = $field['time_format']; + } + $thisYear = date('Y'); + if (isset($field['start_date_years'])) { + $extra['minDate'] = date('Y-m-d', strtotime('-' . ($thisYear - $field['start_date_years']) . ' years')); + } + if (isset($field['end_date_years'])) { + $extra['maxDate'] = date('Y-m-d', strtotime('-' . ($thisYear - $field['end_date_years']) . ' years')); + } + return $extra; + } + + /** + * Get the attributes parameters required for datepicker. + * + * @param array $field + * Field metadata + * + * @return array + * Array ready to pass to $this->addForm('datepicker' as attributes. + */ + public static function getDatePickerAttributes(&$field) { + $attributes = array(); + $dateAttributes = array( + 'start_date_years' => 'minYear', + 'end_date_years' => 'maxYear', + 'date_format' => 'format', + ); + foreach ($dateAttributes as $dateAttribute => $mapTo) { + if (isset($field[$dateAttribute])) { + $attributes[$mapTo] = $field[$dateAttribute]; + } + } + return $attributes; + } + /** * Function to convert mysql to date plugin format. * diff --git a/civicrm/CRM/Utils/Mail/EmailProcessor.php b/civicrm/CRM/Utils/Mail/EmailProcessor.php index a995b7af8f2b1ac87bb09809e05da9e21bbf6078..2e8c14a9917988b2fa1571df8e093d40c707bafa 100644 --- a/civicrm/CRM/Utils/Mail/EmailProcessor.php +++ b/civicrm/CRM/Utils/Mail/EmailProcessor.php @@ -136,11 +136,9 @@ class CRM_Utils_Mail_EmailProcessor { $usedfor = $dao->is_default; $emailActivityTypeId - = (defined('EMAIL_ACTIVITY_TYPE_ID') && EMAIL_ACTIVITY_TYPE_ID) ? EMAIL_ACTIVITY_TYPE_ID : CRM_Core_OptionGroup::getValue( - 'activity_type', - 'Inbound Email', - 'name' - ); + = (defined('EMAIL_ACTIVITY_TYPE_ID') && EMAIL_ACTIVITY_TYPE_ID) + ? EMAIL_ACTIVITY_TYPE_ID + : CRM_Core_OptionGroup::getValue('activity_type', 'Inbound Email', 'name'); if (!$emailActivityTypeId) { CRM_Core_Error::fatal(ts('Could not find a valid Activity Type ID for Inbound Email')); @@ -376,6 +374,14 @@ class CRM_Utils_Mail_EmailProcessor { 'hash' => $hash, 'body' => $text, 'version' => 3, + // Setting is_transactional means it will rollback if + // it crashes part way through creating the bounce. + // If the api were standard & had a create this would be the + // default. Adding the standard api & deprecating this one + // would probably be the + // most consistent way to address this - but this is + // a quick hack. + 'is_transactional' => 1, ); $result = civicrm_api('Mailing', 'event_bounce', $params); break; diff --git a/civicrm/CRM/Utils/PDF/Document.php b/civicrm/CRM/Utils/PDF/Document.php index ff98f858b7b0c2a2a17e6beebb75f8b8c439301b..e841d67ca09461f06fb36d0b0bf671dfffbbec9c 100644 --- a/civicrm/CRM/Utils/PDF/Document.php +++ b/civicrm/CRM/Utils/PDF/Document.php @@ -115,6 +115,7 @@ class CRM_Utils_PDF_Document { $phpWord = \PhpOffice\PhpWord\IOFactory::load($fileName, $formats[$ext]); } + \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(TRUE); //CRM-20015 $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $formats[$ext]); CRM_Utils_System::setHttpHeader('Content-Type', "application/$ext"); diff --git a/civicrm/CRM/Utils/Pager.php b/civicrm/CRM/Utils/Pager.php index 2595bee080b4519b63437003aac8a709ea8cf11a..bd33490a8361b69a2eb9a5e7b650f9e27dd054a1 100644 --- a/civicrm/CRM/Utils/Pager.php +++ b/civicrm/CRM/Utils/Pager.php @@ -112,11 +112,11 @@ class CRM_Utils_Pager extends Pager_Sliding { * page variable, but a different form element for one at the bottom. */ $this->_response['titleTop'] = ts('Page %1 of %2', array( - 1 => '<input size="2" maxlength="3" name="' . self::PAGE_ID . '" type="text" value="' . $this->_response['currentPage'] . '" />', + 1 => '<input size="2" maxlength="4" name="' . self::PAGE_ID . '" type="text" value="' . $this->_response['currentPage'] . '" />', 2 => $this->_response['numPages'], )); $this->_response['titleBottom'] = ts('Page %1 of %2', array( - 1 => '<input size="2" maxlength="3" name="' . self::PAGE_ID_BOTTOM . '" type="text" value="' . $this->_response['currentPage'] . '" />', + 1 => '<input size="2" maxlength="4" name="' . self::PAGE_ID_BOTTOM . '" type="text" value="' . $this->_response['currentPage'] . '" />', 2 => $this->_response['numPages'], )); } diff --git a/civicrm/CRM/Utils/Rule.php b/civicrm/CRM/Utils/Rule.php index 34f346937aef02484eb28e65e349c9964588c08e..034bec2116d060dfa0721a3c30ffdf13293d7c56 100644 --- a/civicrm/CRM/Utils/Rule.php +++ b/civicrm/CRM/Utils/Rule.php @@ -100,10 +100,15 @@ class CRM_Utils_Rule { return FALSE; } - // Ensure the string contains only valid characters: - // For column names: alphanumeric and underscores - // For aliases: backticks, alphanumeric hyphens and underscores. - if (!preg_match('/^((`[\w-]{1,64}`|[\w-]{1,64})\.)?(`[\w-]{1,64}`|[\w-]{1,64})$/i', $str)) { + // Ensure $str conforms to expected format. Not a complete expression of + // what MySQL permits; this should permit the formats CiviCRM generates. + // + // * Table name prefix is optional. + // * Table & column names & aliases: + // * Composed of alphanumeric chars, underscore and hyphens. + // * Maximum length of 64 chars. + // * Optionally surrounded by backticks, in which case spaces also OK. + if (!preg_match('/^((`[\w- ]{1,64}`|[\w-]{1,64})\.)?(`[\w- ]{1,64}`|[\w-]{1,64})$/i', $str)) { return FALSE; } diff --git a/civicrm/CRM/Utils/System.php b/civicrm/CRM/Utils/System.php index 8079cec6f2d61e3c40eeb88c438a2dbbeb6c3210..3ded33fe199cefa353ac9c4ac4ba72585e5e3c20 100644 --- a/civicrm/CRM/Utils/System.php +++ b/civicrm/CRM/Utils/System.php @@ -1391,7 +1391,7 @@ class CRM_Utils_System { * @return mixed */ public static function formatDocUrl($url) { - return preg_replace('#^user/((\w\w/)?stable/)?#', 'user/en/stable/', $url); + return preg_replace('#^user/((\w\w/)?(stable|current)/)?#', 'user/en/stable/', $url); } /** diff --git a/civicrm/CRM/Utils/System/Joomla.php b/civicrm/CRM/Utils/System/Joomla.php index 2758d11758425545aa9c975cc6b6c52fde1ee3b1..8162ac8a615c557b1e1a5638ab70e38e94b1673e 100644 --- a/civicrm/CRM/Utils/System/Joomla.php +++ b/civicrm/CRM/Utils/System/Joomla.php @@ -712,8 +712,20 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base { '', $config->userFrameworkBaseURL ); + // CRM-19453 revisited. Under Windows, the pattern wasn't recognised. + // This is the original pattern, but it doesn't work under Windows. + // By setting the pattern to the one used before the change first and only + // changing it means that the change code only affects Windows users. + $pattern = '|/media/civicrm/.*$|'; + if (DIRECTORY_SEPARATOR == '\\') { + // This regular expression will handle Windows as well as Linux + // and any combination of forward and back slashes in directory + // separators. We only apply it if the directory separator is the one + // used by Windows. + $pattern = '|[\\\\/]media[\\\\/]civicrm[\\\\/].*$|'; + } $siteRoot = preg_replace( - '|/media/civicrm/.*$|', + $pattern, '', $config->imageUploadDir ); diff --git a/civicrm/CRM/Utils/Type.php b/civicrm/CRM/Utils/Type.php index c782e5cec5a6c8574bba69db091b1d3bdb82271d..65b726c98f04b7353ed46b90b424d2060dba5aec 100644 --- a/civicrm/CRM/Utils/Type.php +++ b/civicrm/CRM/Utils/Type.php @@ -143,6 +143,28 @@ class CRM_Utils_Type { return (isset($string)) ? $string : ""; } + /** + * Get the data_type for the field. + * + * @param array $fieldMetadata + * Metadata about the field. + * + * @return string + */ + public static function getDataTypeFromFieldMetadata($fieldMetadata) { + if (isset($fieldMetadata['data_type'])) { + return $fieldMetadata['data_type']; + } + if (empty($fieldMetadata['type'])) { + // I would prefer to throw an e-notice but there is some, + // probably unnecessary logic, that only retrieves activity fields + // if they are 'in the profile' and probably they are not 'in' + // until they are added - which might lead to ? who knows! + return ''; + } + return self::typeToString($fieldMetadata['type']); + } + /** * Helper function to call escape on arrays. * diff --git a/civicrm/Civi/API/Api3SelectQuery.php b/civicrm/Civi/API/Api3SelectQuery.php index 984b1746688ee0436c100dd2aa5117afa55fe5b0..77bdd1b4b79c51732a395277d8258e74d4022963 100644 --- a/civicrm/Civi/API/Api3SelectQuery.php +++ b/civicrm/Civi/API/Api3SelectQuery.php @@ -36,6 +36,7 @@ class Api3SelectQuery extends SelectQuery { * @inheritDoc */ protected function buildWhereClause() { + $filters = array(); foreach ($this->where as $key => $value) { $table_name = NULL; $column_name = NULL; @@ -104,23 +105,37 @@ class Api3SelectQuery extends SelectQuery { // Just ignore this for the $where_clause. continue; } - if (!is_array($value)) { - $this->query->where(array("`$table_name`.`$column_name` = @value"), array( - "@value" => $value, - )); + $operator = is_array($value) ? \CRM_Utils_Array::first(array_keys($value)) : NULL; + if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators())) { + $value = array('=' => $value); } - else { - // We expect only one element in the array, of the form - // "operator" => "rhs". - $operator = \CRM_Utils_Array::first(array_keys($value)); - if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators())) { - $this->query->where(array("{$table_name}.{$column_name} = @value"), array("@value" => $value)); - } - else { - $this->query->where(\CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value)); + $filters[$key] = \CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value); + } + // Support OR groups + if (!empty($this->where['options']['or'])) { + $orGroups = $this->where['options']['or']; + if (is_string($orGroups)) { + $orGroups = array_map('trim', explode(',', $orGroups)); + } + if (!is_array(\CRM_Utils_Array::first($orGroups))) { + $orGroups = array($orGroups); + } + foreach ($orGroups as $orGroup) { + $orClause = array(); + foreach ($orGroup as $key) { + if (!isset($filters[$key])) { + throw new \CiviCRM_API3_Exception("'$key' specified in OR group but not added to params"); + } + $orClause[] = $filters[$key]; + unset($filters[$key]); } + $this->query->where(implode(' OR ', $orClause)); } } + // Add the remaining params using AND + foreach ($filters as $filter) { + $this->query->where($filter); + } } /** diff --git a/civicrm/api/v3/Activity.php b/civicrm/api/v3/Activity.php index 20284c2bb29825783f111def950fc3c782052191..ba87a024a02aba4bef3eefd803af691fe4b75e7b 100644 --- a/civicrm/api/v3/Activity.php +++ b/civicrm/api/v3/Activity.php @@ -230,23 +230,35 @@ function _civicrm_api3_activity_create_spec(&$params) { */ function _civicrm_api3_activity_get_spec(&$params) { $params['tag_id'] = array( - 'name' => 'tag_id', 'title' => 'Tags', 'description' => 'Find activities with specified tags.', 'type' => 1, 'FKClassName' => 'CRM_Core_DAO_Tag', 'FKApiName' => 'Tag', + 'supports_joins' => TRUE, + ); + $params['file_id'] = array( + 'title' => 'Attached Files', + 'description' => 'Find activities with attached files.', + 'type' => 1, + 'FKClassName' => 'CRM_Core_DAO_File', + 'FKApiName' => 'File', ); $params['case_id'] = array( - 'name' => 'case_id', 'title' => 'Cases', 'description' => 'Find activities within specified cases.', 'type' => 1, 'FKClassName' => 'CRM_Case_DAO_Case', 'FKApiName' => 'Case', ); + $params['contact_id'] = array( + 'title' => 'Activity Contact ID', + 'description' => 'Find activities involving this contact (as target, source, OR assignee).', + 'type' => 1, + 'FKClassName' => 'CRM_Contact_DAO_Contact', + 'FKApiName' => 'Contact', + ); $params['target_contact_id'] = array( - 'name' => 'target_contact_id', 'title' => 'Target Contact ID', 'description' => 'Find activities with specified target contact.', 'type' => 1, @@ -254,7 +266,6 @@ function _civicrm_api3_activity_get_spec(&$params) { 'FKApiName' => 'Contact', ); $params['source_contact_id'] = array( - 'name' => 'source_contact_id', 'title' => 'Source Contact ID', 'description' => 'Find activities with specified source contact.', 'type' => 1, @@ -262,7 +273,6 @@ function _civicrm_api3_activity_get_spec(&$params) { 'FKApiName' => 'Contact', ); $params['assignee_contact_id'] = array( - 'name' => 'assignee_contact_id', 'title' => 'Assignee Contact ID', 'description' => 'Find activities with specified assignee contact.', 'type' => 1, @@ -304,55 +314,62 @@ function civicrm_api3_activity_get($params) { } } - if (!empty($params['contact_id'])) { - $activities = CRM_Activity_BAO_Activity::getContactActivity($params['contact_id']); - // BAO function doesn't actually return a contact ID - hack api for now & add to test so when api re-write - // happens it won't get missed. - foreach ($activities as $key => $activityArray) { - $activities[$key]['id'] = $key; + $sql = CRM_Utils_SQL_Select::fragment(); + // Support search by activity_contact + $extraFieldSpecs = array(); + _civicrm_api3_activity_create_spec($extraFieldSpecs); + $options = civicrm_api3('ActivityContact', 'getoptions', array('field' => 'record_type_id')); + $options = $options['values']; + $activityContactOptions = array( + 'contact_id' => NULL, + 'target_contact_id' => array_search('Activity Targets', $options), + 'source_contact_id' => array_search('Activity Source', $options), + 'assignee_contact_id' => array_search('Activity Assignees', $options), + ); + foreach ($activityContactOptions as $activityContactName => $activityContactValue) { + if (!empty($params[$activityContactName])) { + _civicrm_api3_validate_integer($params, $activityContactName, $extraFieldSpecs[$activityContactName], 'Activity'); + if (!is_array($params[$activityContactName])) { + $params[$activityContactName] = array('=' => $params[$activityContactName]); + } + $clause = \CRM_Core_DAO::createSQLFilter('contact_id', $params[$activityContactName]); + $typeClause = $activityContactValue ? 'record_type_id = #typeId AND ' : ''; + $sql->where("a.id IN (SELECT activity_id FROM civicrm_activity_contact WHERE $typeClause !clause)", + array('#typeId' => $activityContactValue, '!clause' => $clause) + ); } } - else { - $sql = CRM_Utils_SQL_Select::fragment(); - // Support search by activity_contact - $options = civicrm_api3('ActivityContact', 'getoptions', array('field' => 'record_type_id')); - $options = $options['values']; - $activityContactOptions = array( - 'target_contact_id' => array_search('Activity Targets', $options), - 'source_contact_id' => array_search('Activity Source', $options), - 'assignee_contact_id' => array_search('Activity Assignees', $options), - ); - foreach ($activityContactOptions as $activityContactName => $activityContactValue) { - if (!empty($params[$activityContactName])) { - if (!is_array($params[$activityContactName])) { - $params[$activityContactName] = array('=' => $params[$activityContactName]); - } - $clause = \CRM_Core_DAO::createSQLFilter('contact_id', $params[$activityContactName]); - $sql->where('a.id IN (SELECT activity_id FROM civicrm_activity_contact WHERE record_type_id = #typeId AND !clause)', - array('#typeId' => $activityContactValue, '!clause' => $clause) - ); - } + if (!empty($params['tag_id'])) { + _civicrm_api3_validate_integer($params, 'tag_id', $extraFieldSpecs['tag_id'], 'Activity'); + if (!is_array($params['tag_id'])) { + $params['tag_id'] = array('=' => $params['tag_id']); } - if (!empty($params['tag_id'])) { - if (!is_array($params['tag_id'])) { - $params['tag_id'] = array('=' => $params['tag_id']); - } - $clause = \CRM_Core_DAO::createSQLFilter('tag_id', $params['tag_id']); - if ($clause) { - $sql->where('a.id IN (SELECT entity_id FROM civicrm_entity_tag WHERE entity_table = "civicrm_activity" AND !clause)', array('!clause' => $clause)); - } + $clause = \CRM_Core_DAO::createSQLFilter('tag_id', $params['tag_id']); + if ($clause) { + $sql->where('a.id IN (SELECT entity_id FROM civicrm_entity_tag WHERE entity_table = "civicrm_activity" AND !clause)', array('!clause' => $clause)); } - if (!empty($params['case_id'])) { - if (!is_array($params['case_id'])) { - $params['case_id'] = array('=' => $params['case_id']); - } - $clause = \CRM_Core_DAO::createSQLFilter('case_id', $params['case_id']); - if ($clause) { - $sql->where('a.id IN (SELECT activity_id FROM civicrm_case_activity WHERE !clause)', array('!clause' => $clause)); - } + } + if (!empty($params['file_id'])) { + _civicrm_api3_validate_integer($params, 'file_id', $extraFieldSpecs['file_id'], 'Activity'); + if (!is_array($params['file_id'])) { + $params['file_id'] = array('=' => $params['file_id']); + } + $clause = \CRM_Core_DAO::createSQLFilter('file_id', $params['file_id']); + if ($clause) { + $sql->where('a.id IN (SELECT entity_id FROM civicrm_entity_file WHERE entity_table = "civicrm_activity" AND !clause)', array('!clause' => $clause)); } - $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'Activity', $sql); } + if (!empty($params['case_id'])) { + _civicrm_api3_validate_integer($params, 'case_id', $extraFieldSpecs['case_id'], 'Activity'); + if (!is_array($params['case_id'])) { + $params['case_id'] = array('=' => $params['case_id']); + } + $clause = \CRM_Core_DAO::createSQLFilter('case_id', $params['case_id']); + if ($clause) { + $sql->where('a.id IN (SELECT activity_id FROM civicrm_case_activity WHERE !clause)', array('!clause' => $clause)); + } + } + $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'Activity', $sql); $options = _civicrm_api3_get_options_from_params($params, FALSE, 'Activity', 'get'); if ($options['is_count']) { return civicrm_api3_create_success($activities, $params, 'Activity', 'get'); @@ -376,6 +393,10 @@ function civicrm_api3_activity_get($params) { * new activities list */ function _civicrm_api3_activity_get_formatResult($params, $activities) { + if (!$activities) { + return $activities; + } + $returns = CRM_Utils_Array::value('return', $params, array()); if (!is_array($returns)) { $returns = str_replace(' ', '', $returns); @@ -398,6 +419,14 @@ function _civicrm_api3_activity_get_formatResult($params, $activities) { $returns['assignee_contact_id'] = 1; } + $tagGet = array('tag_id', 'entity_id'); + foreach (array_keys($returns) as $key) { + if (strpos($key, 'tag_id.') === 0) { + $tagGet[] = $key; + $returns['tag_id'] = 1; + } + } + foreach ($returns as $n => $v) { switch ($n) { case 'assignee_contact_id': @@ -431,13 +460,50 @@ function _civicrm_api3_activity_get_formatResult($params, $activities) { } break; + case 'tag_id': + $tags = civicrm_api3('EntityTag', 'get', array( + 'entity_table' => 'civicrm_activity', + 'entity_id' => array('IN' => array_keys($activities)), + 'return' => $tagGet, + 'options' => array('limit' => 0), + )); + foreach ($tags['values'] as $tag) { + $key = (int) $tag['entity_id']; + unset($tag['entity_id'], $tag['id']); + $activities[$key]['tag_id'][$tag['tag_id']] = $tag; + } + break; + + case 'file_id': + $dao = CRM_Core_DAO::executeQuery("SELECT entity_id, file_id FROM civicrm_entity_file WHERE entity_table = 'civicrm_activity' AND entity_id IN (%1)", + array(1 => array(implode(',', array_keys($activities)), 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES))); + while ($dao->fetch()) { + $activities[$dao->entity_id]['file_id'][] = $dao->file_id; + } + break; + default: if (substr($n, 0, 6) == 'custom') { $returnProperties[$n] = $v; } } } - if (!empty($activities) && (!empty($returnProperties) || !empty($params['contact_id']))) { + + // Legacy extras + if (!empty($params['contact_id'])) { + $statusOptions = CRM_Activity_BAO_Activity::buildOptions('status_id', 'get'); + $typeOptions = CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'validate'); + foreach ($activities as $key => &$activityArray) { + if (!empty($activityArray['status_id'])) { + $activityArray['status'] = $statusOptions[$activityArray['status_id']]; + } + if (!empty($activityArray['activity_type_id'])) { + $activityArray['activity_name'] = $typeOptions[$activityArray['activity_type_id']]; + } + } + } + + if (!empty($returnProperties) || !empty($params['contact_id'])) { foreach ($activities as $activityId => $values) { //@todo - should possibly load activity type id if not loaded (update with id) _civicrm_api3_custom_data_get($activities[$activityId], CRM_Utils_Array::value('check_permissions', $params), 'Activity', $activityId, NULL, CRM_Utils_Array::value('activity_type_id', $values)); diff --git a/civicrm/api/v3/Case.php b/civicrm/api/v3/Case.php index 8cfdfe1d2db9c0e34f1af597ee43c199c658e26a..efddd0904b974408d1435e43ad9eba5ca6505cb7 100644 --- a/civicrm/api/v3/Case.php +++ b/civicrm/api/v3/Case.php @@ -453,6 +453,11 @@ function _civicrm_api3_case_format_params(&$params) { function civicrm_api3_case_getList($params) { require_once 'api/v3/Generic/Getlist.php'; require_once 'api/v3/CaseContact.php'; + //CRM:19956 - Assign case_id param if both id and case_id is passed to retrieve the case + if (!empty($params['id']) && !empty($params['params']) && !empty($params['params']['case_id'])) { + $params['params']['case_id'] = array('IN' => $params['id']); + unset($params['id']); + } $params['id_field'] = 'case_id'; $params['label_field'] = $params['search_field'] = 'contact_id.sort_name'; $params['description_field'] = array( @@ -463,6 +468,7 @@ function civicrm_api3_case_getList($params) { 'case_id.start_date', ); $apiRequest = array( + 'version' => 3, 'entity' => 'CaseContact', 'action' => 'getlist', 'params' => $params, diff --git a/civicrm/api/v3/Contact.php b/civicrm/api/v3/Contact.php index af3028d59c1e66dff29d88138dd2efe34a9373ec..773068f4bbf23e73965e62061b47433ad044e25f 100644 --- a/civicrm/api/v3/Contact.php +++ b/civicrm/api/v3/Contact.php @@ -376,6 +376,37 @@ function _civicrm_api3_contact_get_supportanomalies(&$params, &$options) { unset($params['filter.group_id']); $options['input_params']['group'] = $groups; } + if (isset($params['group'])) { + $groups = $params['group']; + $allGroups = CRM_Core_PseudoConstant::group(); + if (is_array($groups) && in_array(key($groups), CRM_Core_DAO::acceptedSQLOperators(), TRUE)) { + // Get the groups array. + $groupsArray = $groups[key($groups)]; + foreach ($groupsArray as &$group) { + if (!is_numeric($group) && array_search($group, $allGroups)) { + $group = array_search($group, $allGroups); + } + } + // Now reset the $groups array with the ids not the titles. + $groups[key($groups)] = $groupsArray; + } + // handle format like 'group' => array('title1', 'title2'). + elseif (is_array($groups)) { + foreach ($groups as $k => &$group) { + if (!is_numeric($group) && array_search($group, $allGroups)) { + $group = array_search($group, $allGroups); + } + if (!is_numeric($k) && array_search($k, $allGroups)) { + unset($groups[$k]); + $groups[array_search($k, $allGroups)] = $group; + } + } + } + elseif (!is_numeric($groups) && array_search($groups, $allGroups)) { + $groups = array_search($groups, $allGroups); + } + $params['group'] = $groups; + } } /** @@ -1085,7 +1116,7 @@ function civicrm_api3_contact_merge($params) { 'srcID' => $params['to_remove_id'], 'dstID' => $params['to_keep_id'], ), - ), array(), $params['mode'], $params['auto_flip'])) != FALSE) { + ), array(), $params['mode'])) != FALSE) { return civicrm_api3_create_success($result, $params); } throw new CiviCRM_API3_Exception('Merge failed'); @@ -1111,10 +1142,6 @@ function _civicrm_api3_contact_merge_spec(&$params) { 'type' => CRM_Utils_Type::T_INT, 'api.aliases' => array('other_id'), ); - $params['auto_flip'] = array( - 'title' => 'Swap destination and source to retain lowest id?', - 'api.default' => TRUE, - ); $params['mode'] = array( // @todo need more detail on what this means. 'title' => 'Dedupe mode', diff --git a/civicrm/api/v3/Contribution.php b/civicrm/api/v3/Contribution.php index 976ad8cc654e2be235a43ca1fc7eabb9f3adfecb..c6e2b1e7abbb894e0ec35924c18cfa0dc08ca5a1 100644 --- a/civicrm/api/v3/Contribution.php +++ b/civicrm/api/v3/Contribution.php @@ -240,19 +240,69 @@ function _civicrm_api3_contribution_delete_spec(&$params) { function civicrm_api3_contribution_get($params) { $mode = CRM_Contact_BAO_Query::MODE_CONTRIBUTE; + $additionalOptions = _civicrm_api3_contribution_get_support_nonunique_returns($params); $returnProperties = CRM_Contribute_BAO_Query::defaultReturnProperties($mode); - $contributions = _civicrm_api3_get_using_query_object('Contribution', $params, array(), NULL, $mode, $returnProperties); + $contributions = _civicrm_api3_get_using_query_object('Contribution', $params, $additionalOptions, NULL, $mode, $returnProperties); foreach ($contributions as $id => $contribution) { $softContribution = CRM_Contribute_BAO_ContributionSoft::getSoftContribution($id, TRUE); $contributions[$id] = array_merge($contribution, $softContribution); // format soft credit for backward compatibility _civicrm_api3_format_soft_credit($contributions[$id]); + _civicrm_api3_contribution_add_supported_fields($contributions[$id]); + } return civicrm_api3_create_success($contributions, $params, 'Contribution', 'get'); } +/** + * Fix the return values to reflect cases where the schema has been changed. + * + * At the query object level using uniquenames dismbiguates between tables. + * + * However, adding uniquename can change inputs accepted by the api, so we need + * to ensure we are asking for the unique name return fields. + * + * @param array $params + * + * @return array + * @throws \API_Exception + */ +function _civicrm_api3_contribution_get_support_nonunique_returns($params) { + $additionalOptions = array(); + $options = _civicrm_api3_get_options_from_params($params, TRUE); + foreach (array('check_number', 'address_id') as $changedVariable) { + if (isset($options['return']) && !empty($options['return'][$changedVariable])) { + $additionalOptions['return']['contribution_' . $changedVariable] = 1; + } + } + return $additionalOptions; +} + +/** + * Support for supported output variables. + * + * @param $contribution + */ +function _civicrm_api3_contribution_add_supported_fields(&$contribution) { + // These are output fields that are supported in our test contract. + // Arguably we should also do the same with 'campaign_id' & + // 'source' - which are also fields being rendered with unique names. + // That seems more consistent with other api where we output the actual field names. + $outputAliases = array( + 'contribution_check_number' => 'check_number', + 'contribution_address_id' => 'address_id', + 'payment_instrument_id' => 'instrument_id', + ); + foreach ($outputAliases as $returnName => $copyTo) { + if (array_key_exists($returnName, $contribution)) { + $contribution[$copyTo] = $contribution[$returnName]; + } + } + +} + /** * Get number of contacts matching the supplied criteria. * @@ -528,7 +578,7 @@ function _civicrm_api3_contribution_completetransaction_spec(&$params) { $params['trxn_date'] = array( 'title' => 'Transaction Date', 'description' => 'Date this transaction occurred', - 'type' => CRM_Utils_Type::T_DATE, + 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME, ); } @@ -552,9 +602,12 @@ function civicrm_api3_contribution_repeattransaction(&$params) { $input = $ids = array(); civicrm_api3_verify_one_mandatory($params, NULL, array('contribution_recur_id', 'original_contribution_id')); if (empty($params['original_contribution_id'])) { + // CRM-19873 call with test mode. $params['original_contribution_id'] = civicrm_api3('contribution', 'getvalue', array( 'return' => 'id', + 'contribution_status_id' => array('IN' => array('Completed')), 'contribution_recur_id' => $params['contribution_recur_id'], + 'contribution_test' => CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionRecur', $params['contribution_recur_id'], 'is_test'), 'options' => array('limit' => 1, 'sort' => 'id DESC'), )); } @@ -680,7 +733,7 @@ function _civicrm_api3_contribution_repeattransaction_spec(&$params) { $params['receive_date'] = array( 'title' => 'Contribution Receive Date', 'name' => 'receive_date', - 'type' => CRM_Utils_Type::T_DATE, + 'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME, 'api.default' => 'now', ); $params['trxn_id'] = array( diff --git a/civicrm/api/v3/Extension.php b/civicrm/api/v3/Extension.php index 3862ac0cec739a4b5ca03a4e9fb7a4ca681f2ee8..367ad7b66d7492161ee3edd50dea318485f4f4fb 100644 --- a/civicrm/api/v3/Extension.php +++ b/civicrm/api/v3/Extension.php @@ -244,7 +244,9 @@ function civicrm_api3_extension_download($params) { } CRM_Extension_System::singleton()->getCache()->flush(); CRM_Extension_System::singleton(TRUE); - CRM_Extension_System::singleton()->getManager()->install(array($params['key'])); + if (CRM_Utils_Array::value('install', $params, TRUE)) { + CRM_Extension_System::singleton()->getManager()->install(array($params['key'])); + } return civicrm_api3_create_success(); } @@ -265,6 +267,12 @@ function _civicrm_api3_extension_download_spec(&$fields) { 'type' => CRM_Utils_Type::T_STRING, 'description' => 'Optional as the system can determine the url automatically for public extensions', ); + $fields['install'] = array( + 'title' => 'Auto-install', + 'type' => CRM_Utils_Type::T_STRING, + 'description' => 'Automatically install the downloaded extension', + 'api.default' => TRUE, + ); } /** diff --git a/civicrm/api/v3/GroupContact.php b/civicrm/api/v3/GroupContact.php index 50378c1d96fe464d2885dccc734935d93f82a5d4..53f055e82b856ee0128c2fcc367c0c8c51a7cc14 100644 --- a/civicrm/api/v3/GroupContact.php +++ b/civicrm/api/v3/GroupContact.php @@ -148,17 +148,17 @@ function civicrm_api3_group_contact_create($params) { function civicrm_api3_group_contact_delete($params) { $checkParams = $params; if (!empty($checkParams['status']) && in_array($checkParams['status'], array('Removed', 'Deleted'))) { - $checkParams['status'] = 'Added'; + $checkParams['status'] = array('IN' => array('Added', 'Pending')); } elseif (!empty($checkParams['status']) && $checkParams['status'] == 'Added') { - $checkParams['status'] = 'Removed'; + $checkParams['status'] = array('IN' => array('Pending', 'Removed')); } elseif (!empty($checkParams['status'])) { unset($checkParams['status']); } $groupContact = civicrm_api3('GroupContact', 'get', $checkParams); if ($groupContact['count'] == 0 && !empty($params['skip_undelete'])) { - $checkParams['status'] = 'removed'; + $checkParams['status'] = array('IN' => array('Removed', 'Pending')); } $groupContact2 = civicrm_api3('GroupContact', 'get', $checkParams); if ($groupContact['count'] == 0 && $groupContact2['count'] == 0) { diff --git a/civicrm/api/v3/Job.php b/civicrm/api/v3/Job.php index 381ce176653deb8b6fe26be63f15ed4ae80104ca..89f4fb0d3be1ae0fb5e2c64233ac84426bb7b292 100644 --- a/civicrm/api/v3/Job.php +++ b/civicrm/api/v3/Job.php @@ -390,7 +390,7 @@ function civicrm_api3_job_fetch_activities($params) { } catch (Exception $e) { $lock->release(); - return civicrm_api3_create_error('Process Activities failed'); + return civicrm_api3_create_error($e->getMessage()); } } @@ -487,11 +487,9 @@ function civicrm_api3_job_process_batch_merge($params) { )); } $gid = CRM_Utils_Array::value('gid', $params); - $mode = CRM_Utils_Array::value('mode', $params, 'safe'); - $autoFlip = CRM_Utils_Array::value('auto_flip', $params, TRUE); - $result = CRM_Dedupe_Merger::batchMerge($rule_group_id, $gid, $mode, $autoFlip, 1, 2, CRM_Utils_Array::value('criteria', $params, array()), CRM_Utils_Array::value('check_permissions', $params)); + $result = CRM_Dedupe_Merger::batchMerge($rule_group_id, $gid, $mode, 1, 2, CRM_Utils_Array::value('criteria', $params, array()), CRM_Utils_Array::value('check_permissions', $params)); return civicrm_api3_create_success($result, $params); } diff --git a/civicrm/api/v3/Logging.php b/civicrm/api/v3/Logging.php index c1a9010a777c08386c2da2c993cbea127b118863..3287b8794f675febda5dc29548e21dbcc7077f8f 100644 --- a/civicrm/api/v3/Logging.php +++ b/civicrm/api/v3/Logging.php @@ -44,7 +44,8 @@ function civicrm_api3_logging_revert($params) { $schema = new CRM_Logging_Schema(); $reverter = new CRM_Logging_Reverter($params['log_conn_id'], CRM_Utils_Array::value('log_date', $params)); - $reverter->calculateDiffsFromLogConnAndDate($schema->getLogTablesForContact()); + $tables = !empty($params['tables']) ? (array) $params['tables'] : $schema->getLogTablesForContact(); + $reverter->calculateDiffsFromLogConnAndDate($tables); $reverter->revert(); return civicrm_api3_create_success(1); } @@ -73,6 +74,12 @@ function _civicrm_api3_logging_revert_spec(&$params) { 'api.default' => '10 SECOND', 'description' => ts('Used when log_date is passed in'), ); + + $params['tables'] = array( + 'title' => ts('Tables to revert'), + 'type' => CRM_Utils_Type::T_STRING, + 'description' => ts('Tables to revert, if not set all contact-referring entities will be reverted'), + ); } /** @@ -89,7 +96,8 @@ function civicrm_api3_logging_get($params) { $schema = new CRM_Logging_Schema(); $interval = (empty($params['log_date'])) ? NULL : $params['interval']; $differ = new CRM_Logging_Differ($params['log_conn_id'], CRM_Utils_Array::value('log_date', $params), $interval); - return civicrm_api3_create_success($differ->getAllChangesForConnection($schema->getLogTablesForContact())); + $tables = !empty($params['tables']) ? (array) $params['tables'] : $schema->getLogTablesForContact(); + return civicrm_api3_create_success($differ->getAllChangesForConnection($tables)); } /** @@ -116,4 +124,9 @@ function _civicrm_api3_logging_get_spec(&$params) { 'api.default' => '10 SECOND', 'description' => ts('Used when log_date is passed in'), ); + $params['tables'] = array( + 'title' => ts('Tables to query'), + 'type' => CRM_Utils_Type::T_STRING, + 'description' => ts('Tables to query, if not set all contact-referring entities will be queried'), + ); } diff --git a/civicrm/api/v3/MailingGroup.php b/civicrm/api/v3/MailingGroup.php index 0dbac4513f799bf49d8811d6faa7e37932d747f5..9a7a6ef67af572b629225fea722a2088d9cdd0c0 100644 --- a/civicrm/api/v3/MailingGroup.php +++ b/civicrm/api/v3/MailingGroup.php @@ -40,7 +40,13 @@ * to indicate this entire api entity is deprecated */ function _civicrm_api3_mailing_group_deprecation() { - return 'The MailingGroup api is deprecated. Use the mailing_event apis instead.'; + $message = 'This action is deprecated. Use the mailing_event API instead.'; + return array( + 'event_unsubscribe' => $message, + 'event_domain_unsubscribe' => $message, + 'event_resubscribe' => $message, + 'event_subscribe' => $message, + ); } /** diff --git a/civicrm/api/v3/MembershipType.php b/civicrm/api/v3/MembershipType.php index d1db1fec13d1f29f0ae0092a52e9cb3093088dd4..a8b29405c522e96e776998e287cddd31fe2768d7 100644 --- a/civicrm/api/v3/MembershipType.php +++ b/civicrm/api/v3/MembershipType.php @@ -66,6 +66,7 @@ function _civicrm_api3_membership_type_create_spec(&$params) { $params['name']['api.required'] = 1; $params['duration_unit']['api.required'] = 1; $params['duration_interval']['api.required'] = 1; + $params['period_type']['api.required'] = 1; $params['is_active']['api.default'] = 1; } diff --git a/civicrm/api/v3/PriceSet.php b/civicrm/api/v3/PriceSet.php index b31ced3848a9fa9ce3659a908cd20d3202391181..b7b15e6019c1b2bfdbe41205dce6a69666613540 100644 --- a/civicrm/api/v3/PriceSet.php +++ b/civicrm/api/v3/PriceSet.php @@ -91,9 +91,11 @@ function civicrm_api3_price_set_get($params) { return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params); } $result = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE); - // Fetch associated entities - foreach ($result as &$item) { - $item['entity'] = CRM_Price_BAO_PriceSet::getUsedBy($item['id'], 'entity'); + // Fetch associated entities if the return has not been previously limited. + if (!isset($params['return'])) { + foreach ($result as &$item) { + $item['entity'] = CRM_Price_BAO_PriceSet::getUsedBy($item['id'], 'entity'); + } } return civicrm_api3_create_success($result, $params); } diff --git a/civicrm/api/v3/Profile.php b/civicrm/api/v3/Profile.php index c948d7a3780d8f643e4b3afe1d96d0a962343223..7a0e431751b166baa12c83585b48935db5902637 100644 --- a/civicrm/api/v3/Profile.php +++ b/civicrm/api/v3/Profile.php @@ -657,7 +657,7 @@ function _civicrm_api3_map_profile_fields_to_entity(&$field) { 'total_amount' => 'contribution', 'receive_date' => 'contribution', 'payment_instrument' => 'contribution', - 'check_number' => 'contribution', + 'contribution_check_number' => 'contribution', 'contribution_status_id' => 'contribution', 'soft_credit' => 'contribution', 'soft_credit_type' => 'contribution_soft', diff --git a/civicrm/api/v3/examples/Activity/ContactRefCustomField.php b/civicrm/api/v3/examples/Activity/ContactRefCustomField.php index adf4230f1357246e34874a2e519e38f1b2f8259c..b830541308b82072a34e0c925ac11be684ccff42 100644 --- a/civicrm/api/v3/examples/Activity/ContactRefCustomField.php +++ b/civicrm/api/v3/examples/Activity/ContactRefCustomField.php @@ -10,7 +10,7 @@ function activity_create_example() { $params = array( 'source_contact_id' => 1, - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '2011-06-02 14:36:13', 'status_id' => 2, @@ -57,7 +57,7 @@ function activity_create_expectedresult() { '1' => array( 'id' => '1', 'source_record_id' => '', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '20110602143613', 'duration' => '120', diff --git a/civicrm/api/v3/examples/Activity/ContactRefCustomFieldGet.php b/civicrm/api/v3/examples/Activity/ContactRefCustomFieldGet.php index 6cd8188ccb393c55a17101bc108da5ca80653dd7..8603caf946b6fc24ebc48fdbaa3c5fc1702b4a6e 100644 --- a/civicrm/api/v3/examples/Activity/ContactRefCustomFieldGet.php +++ b/civicrm/api/v3/examples/Activity/ContactRefCustomFieldGet.php @@ -48,7 +48,7 @@ function activity_get_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '2011-06-02 14:36:13', 'duration' => '120', @@ -60,13 +60,14 @@ function activity_get_expectedresult() { 'is_auto' => 0, 'is_current_revision' => '1', 'is_deleted' => 0, - 'source_contact_id' => '1', + 'is_star' => 0, 'custom_1' => 'defaultValue', - 'custom_1_1' => 'defaultValue', + 'custom_2_id' => '1', 'custom_2' => 'Anderson, Anthony', + 'source_contact_id' => '1', + 'custom_1_1' => 'defaultValue', 'custom_2_1' => 'Anderson, Anthony', 'custom_2_1_id' => '1', - 'custom_2_id' => '1', ), ), ); diff --git a/civicrm/api/v3/examples/Activity/Create.php b/civicrm/api/v3/examples/Activity/Create.php index 6615362918b295414621933769e8d94e5811f78c..a380f128d0bea2bd72619be3540c56ad83fd22a6 100644 --- a/civicrm/api/v3/examples/Activity/Create.php +++ b/civicrm/api/v3/examples/Activity/Create.php @@ -8,7 +8,7 @@ function activity_create_example() { $params = array( 'source_contact_id' => 1, - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '2011-06-02 14:36:13', 'status_id' => 2, @@ -55,7 +55,7 @@ function activity_create_expectedresult() { '1' => array( 'id' => '1', 'source_record_id' => '', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '20110602143613', 'duration' => '120', @@ -87,7 +87,7 @@ function activity_create_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testActivityCreateCustom" +* The test that created it is called "testActivityCreateCustomSubType" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ActivityTest.php * diff --git a/civicrm/api/v3/examples/Activity/DateTimeHigh.php b/civicrm/api/v3/examples/Activity/DateTimeHigh.php index 4833a1885bf38bed171fe692169aa549e6696420..54d9ace23213e44e993e6745fe368c3d39c8cd89 100644 --- a/civicrm/api/v3/examples/Activity/DateTimeHigh.php +++ b/civicrm/api/v3/examples/Activity/DateTimeHigh.php @@ -49,7 +49,7 @@ function activity_get_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'Make-it-Happen Meeting', 'activity_date_time' => '2011-01-01 00:00:00', 'duration' => '120', diff --git a/civicrm/api/v3/examples/Activity/DateTimeLow.php b/civicrm/api/v3/examples/Activity/DateTimeLow.php index f7052bc2aaf522bcfcfb72769808c733a8f59c97..e670e377e2f7884d2c6deb0ae7ec9d3e3e8e2235 100644 --- a/civicrm/api/v3/examples/Activity/DateTimeLow.php +++ b/civicrm/api/v3/examples/Activity/DateTimeLow.php @@ -48,7 +48,7 @@ function activity_get_expectedresult() { 'values' => array( '0' => array( 'id' => '2', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'Make-it-Happen Meeting', 'activity_date_time' => '2012-02-16 00:00:00', 'duration' => '120', diff --git a/civicrm/api/v3/examples/Activity/Get.php b/civicrm/api/v3/examples/Activity/Get.php index ac52fab2604d9ab8efdcc7057f377262d7ac40d0..1d981955898e80add961209b2d70ae4ae3e40846 100644 --- a/civicrm/api/v3/examples/Activity/Get.php +++ b/civicrm/api/v3/examples/Activity/Get.php @@ -8,7 +8,7 @@ function activity_get_example() { $params = array( 'contact_id' => 1, - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'sequential' => 1, 'return.custom_1' => 1, ); @@ -49,7 +49,7 @@ function activity_get_expectedresult() { '0' => array( 'source_contact_id' => '1', 'id' => '1', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'location' => 'Pennsylvania', 'activity_date_time' => '2011-06-02 14:36:13', diff --git a/civicrm/api/v3/examples/Activity/GetFields.php b/civicrm/api/v3/examples/Activity/GetFields.php index a6269d125a82742fe69910bd8cfd96fa8015de5c..76bca1d50070e383df652783a3fbed50260e4ca3 100644 --- a/civicrm/api/v3/examples/Activity/GetFields.php +++ b/civicrm/api/v3/examples/Activity/GetFields.php @@ -47,6 +47,9 @@ function activity_getfields_expectedresult() { 'type' => 1, 'title' => 'Source Record', 'description' => 'Artificial FK to original transaction (e.g. contribution) IF it is not an Activity. Table can be figured out through activity_type_id, and further through component registry.', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', ), 'activity_type_id' => array( 'name' => 'activity_type_id', @@ -59,6 +62,9 @@ function activity_getfields_expectedresult() { 'headerPattern' => '/(activity.)?type(.id$)/i', 'export' => TRUE, 'default' => '1', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -78,8 +84,12 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.activity_date_time', 'headerPattern' => '/(activity.)?date(.time$)?/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select Date', + 'format' => 'activityDateTime', ), ), 'phone_id' => array( @@ -87,6 +97,9 @@ function activity_getfields_expectedresult() { 'type' => 1, 'title' => 'Phone (called) ID', 'description' => 'Phone ID of the number called (optional - used if an existing phone number is selected).', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'FKClassName' => 'CRM_Core_DAO_Phone', 'html' => array( 'type' => 'EntityRef', @@ -102,6 +115,9 @@ function activity_getfields_expectedresult() { 'description' => 'Phone number in case the number does not exist in the civicrm_phone table.', 'maxlength' => 64, 'size' => 30, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -113,6 +129,9 @@ function activity_getfields_expectedresult() { 'type' => 1, 'title' => 'Priority', 'description' => 'ID of the priority given to this activity. Foreign key to civicrm_option_value.', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -128,6 +147,9 @@ function activity_getfields_expectedresult() { 'type' => 1, 'title' => 'Parent Activity Id', 'description' => 'Parent meeting ID (if this is a follow-up item). This is not currently implemented', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'FKClassName' => 'CRM_Activity_DAO_Activity', 'FKApiName' => 'Activity', ), @@ -135,6 +157,9 @@ function activity_getfields_expectedresult() { 'name' => 'is_auto', 'type' => 16, 'title' => 'Auto', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', ), 'relationship_id' => array( 'name' => 'relationship_id', @@ -142,6 +167,9 @@ function activity_getfields_expectedresult() { 'title' => 'Relationship Id', 'description' => 'FK to Relationship ID', 'default' => 'NULL', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'FKClassName' => 'CRM_Contact_DAO_Relationship', 'FKApiName' => 'Relationship', ), @@ -154,6 +182,9 @@ function activity_getfields_expectedresult() { 'headerPattern' => '/(is.)?(current.)?(revision|version(ing)?)/i', 'export' => TRUE, 'default' => '1', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'CheckBox', ), @@ -163,6 +194,9 @@ function activity_getfields_expectedresult() { 'type' => 1, 'title' => 'Original Activity ID ', 'description' => 'Activity ID of the first activity record in versioning chain.', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'FKClassName' => 'CRM_Activity_DAO_Activity', 'FKApiName' => 'Activity', ), @@ -170,6 +204,9 @@ function activity_getfields_expectedresult() { 'name' => 'weight', 'type' => 1, 'title' => 'Order', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'size' => 6, @@ -185,6 +222,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.is_star', 'headerPattern' => '/(activity.)?(star|favorite)/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', ), 'id' => array( 'name' => 'id', @@ -195,6 +235,9 @@ function activity_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_activity.id', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'uniqueName' => 'activity_id', 'api.aliases' => array( '0' => 'activity_id', @@ -211,6 +254,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.subject', 'headerPattern' => '/(activity.)?subject/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -227,6 +273,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.duration', 'headerPattern' => '/(activity.)?duration(s)?$/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'size' => 6, @@ -245,6 +294,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.location', 'headerPattern' => '/(activity.)?location$/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -261,6 +313,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.details', 'headerPattern' => '/(activity.)?detail(s)?$/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'RichTextEditor', 'rows' => 2, @@ -276,6 +331,9 @@ function activity_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_activity.status_id', 'headerPattern' => '/(activity.)?status(.label$)?/i', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -298,6 +356,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.is_test', 'headerPattern' => '/(is.)?test(.activity)?/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', ), @@ -309,6 +370,9 @@ function activity_getfields_expectedresult() { 'title' => 'Activity Medium', 'description' => 'Activity Medium, Implicit FK to civicrm_option_value where option_group = encounter_medium.', 'default' => 'NULL', + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -327,6 +391,9 @@ function activity_getfields_expectedresult() { 'description' => 'Currently being used to store result id for survey activity, FK to option value.', 'maxlength' => 255, 'size' => 45, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -342,6 +409,9 @@ function activity_getfields_expectedresult() { 'where' => 'civicrm_activity.is_deleted', 'headerPattern' => '/(activity.)?(trash|deleted)/i', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Text', ), @@ -355,6 +425,9 @@ function activity_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_activity.campaign_id', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'FKClassName' => 'CRM_Campaign_DAO_Campaign', 'html' => array( 'type' => 'CheckBox', @@ -377,6 +450,9 @@ function activity_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_activity.engagement_level', 'export' => TRUE, + 'table_name' => 'civicrm_activity', + 'entity' => 'Activity', + 'bao' => 'CRM_Activity_BAO_Activity', 'html' => array( 'type' => 'Select', 'size' => 6, diff --git a/civicrm/api/v3/examples/Activity/GetTargetandAssigneeName.php b/civicrm/api/v3/examples/Activity/GetTargetandAssigneeName.php index 77b45f7bbbce1204e447491bc1bdc0a560e41c5c..003b333d37daf5152ef254d97c2174410ae6c884 100644 --- a/civicrm/api/v3/examples/Activity/GetTargetandAssigneeName.php +++ b/civicrm/api/v3/examples/Activity/GetTargetandAssigneeName.php @@ -48,16 +48,18 @@ function activity_getsingle_expectedresult() { $expectedResult = array( 'id' => '1', 'subject' => 'Make-it-Happen Meeting', - 'source_contact_id' => '8', + 'source_contact_id' => '6', 'source_contact_name' => 'D Bug', - 'target_contact_id' => array('5', '6'), + 'target_contact_id' => array( + '1' => '4', + ), 'target_contact_name' => array( - '5' => 'A Cat', - '6' => 'B Good', + '3' => 'A Cat', + '4' => 'B Good', ), - 'assignee_contact_id' => array('7'), + 'assignee_contact_id' => array(), 'assignee_contact_name' => array( - '7' => 'C Shore', + '5' => 'C Shore', ), ); diff --git a/civicrm/api/v3/examples/Activity/ReturnAssigneeContact.php b/civicrm/api/v3/examples/Activity/ReturnAssigneeContact.php index 574a34a7b27cbf6859706b4e56e45f831e50920c..4042c39fff4ae8946b4ced77286657829cdf52ae 100644 --- a/civicrm/api/v3/examples/Activity/ReturnAssigneeContact.php +++ b/civicrm/api/v3/examples/Activity/ReturnAssigneeContact.php @@ -52,7 +52,7 @@ function activity_get_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'activity_type_id' => '51', + 'activity_type_id' => '55', 'subject' => 'test activity type id', 'activity_date_time' => '2011-06-02 14:36:13', 'duration' => '120', diff --git a/civicrm/api/v3/examples/ActivityType/Create.php b/civicrm/api/v3/examples/ActivityType/Create.php index ac5da5ced8f491528a8f30fffd2034132ef297ef..b3a231503be5467655f41d4ebed3d3bb47631938 100644 --- a/civicrm/api/v3/examples/ActivityType/Create.php +++ b/civicrm/api/v3/examples/ActivityType/Create.php @@ -49,13 +49,13 @@ function activity_type_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 784, + 'id' => 849, 'values' => array( - '784' => array( - 'id' => '784', + '849' => array( + 'id' => '849', 'option_group_id' => '2', 'label' => 'send out letters', - 'value' => '51', + 'value' => '55', 'name' => 'send out letters', 'grouping' => '', 'filter' => 0, @@ -68,6 +68,8 @@ function activity_type_create_expectedresult() { 'component_id' => '', 'domain_id' => '', 'visibility_id' => '', + 'icon' => '', + 'color' => '', ), ), 'deprecated' => 'The ActivityType api is deprecated. Please use the OptionValue api instead.', diff --git a/civicrm/api/v3/examples/ActivityType/Get.php b/civicrm/api/v3/examples/ActivityType/Get.php index a2158500c1a15e8560c2107d1af44ecdc46117bd..3befa05035d7e485d1fc4e5bb1c4229caf9c3886 100644 --- a/civicrm/api/v3/examples/ActivityType/Get.php +++ b/civicrm/api/v3/examples/ActivityType/Get.php @@ -41,7 +41,7 @@ function activity_type_get_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 50, + 'count' => 54, 'values' => array( '1' => 'Meeting', '2' => 'Phone Call', diff --git a/civicrm/api/v3/examples/Constant/Get.php b/civicrm/api/v3/examples/Constant/Get.php index a6c11087a0d3d0422064ff1c45469894c85443d5..561e259a1eb5ccce15ed53f2f6dc3ee265716562 100644 --- a/civicrm/api/v3/examples/Constant/Get.php +++ b/civicrm/api/v3/examples/Constant/Get.php @@ -43,7 +43,7 @@ function constant_get_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 32, + 'count' => 36, 'values' => array( '1' => 'Meeting', '2' => 'Phone Call', diff --git a/civicrm/api/v3/examples/Contact/APIChainedArray.php b/civicrm/api/v3/examples/Contact/APIChainedArray.php index 839b99005e172748227e91375573100ec4d88a9b..35f3a002d46afc69d73b8cab12a0a1b141c83bf9 100644 --- a/civicrm/api/v3/examples/Contact/APIChainedArray.php +++ b/civicrm/api/v3/examples/Contact/APIChainedArray.php @@ -10,7 +10,7 @@ */ function contact_get_example() { $params = array( - 'id' => 1, + 'id' => 3, 'api.website.get' => array(), 'api.Contribution.get' => array( 'total_amount' => '120.00', @@ -50,10 +50,10 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'xyz3, abc3', @@ -89,8 +89,8 @@ function contact_get_expectedresult() { 'sic_code' => '', 'contact_is_deleted' => 0, 'current_employer' => '', - 'address_id' => '2', - 'street_address' => '1 my road', + 'address_id' => '', + 'street_address' => '', 'supplemental_address_1' => '', 'supplemental_address_2' => '', 'city' => '', @@ -118,7 +118,7 @@ function contact_get_expectedresult() { 'state_province_name' => '', 'state_province' => '', 'country' => '', - 'id' => '1', + 'id' => '3', 'api.website.get' => array( 'is_error' => 0, 'version' => 3, @@ -127,7 +127,7 @@ function contact_get_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'contact_id' => '1', + 'contact_id' => '3', 'url' => 'http://civicrm.org', ), ), @@ -139,7 +139,7 @@ function contact_get_expectedresult() { 'id' => 2, 'values' => array( '0' => array( - 'contact_id' => '1', + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'xyz3, abc3', @@ -159,10 +159,11 @@ function contact_get_expectedresult() { 'thankyou_date' => '', 'contribution_source' => 'SSF', 'amount_level' => '', + 'contribution_recur_id' => '', 'is_test' => 0, 'is_pay_later' => 0, 'contribution_status_id' => '1', - 'check_number' => '', + 'contribution_check_number' => '', 'contribution_campaign_id' => '', 'financial_type_id' => '1', 'financial_type' => 'Donation', @@ -174,16 +175,17 @@ function contact_get_expectedresult() { 'fulfilled_date' => '', 'contribution_start_date' => '', 'contribution_end_date' => '', - 'contribution_recur_id' => '', 'financial_account_id' => '1', 'accounting_code' => '4200', + 'campaign_id' => '', + 'contribution_campaign_title' => '', 'contribution_note' => '', 'contribution_batch' => '', 'contribution_status' => 'Completed', 'payment_instrument' => 'Credit Card', 'payment_instrument_id' => '1', 'instrument_id' => '1', - 'contribution_check_number' => '', + 'check_number' => '', 'id' => '2', 'contribution_type_id' => '1', ), diff --git a/civicrm/api/v3/examples/Contact/APIChainedArrayFormats.php b/civicrm/api/v3/examples/Contact/APIChainedArrayFormats.php index c79c27a426c837154073ac7659f748591ba201cd..5145682730e3646cb0cc4d939317e9cfad066e24 100644 --- a/civicrm/api/v3/examples/Contact/APIChainedArrayFormats.php +++ b/civicrm/api/v3/examples/Contact/APIChainedArrayFormats.php @@ -10,7 +10,7 @@ */ function contact_get_example() { $params = array( - 'id' => 1, + 'id' => 3, 'api.website.getValue' => array( 'return' => 'url', ), @@ -51,10 +51,10 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'xyz3, abc3', @@ -90,8 +90,8 @@ function contact_get_expectedresult() { 'sic_code' => '', 'contact_is_deleted' => 0, 'current_employer' => '', - 'address_id' => '2', - 'street_address' => '1 my road', + 'address_id' => '', + 'street_address' => '', 'supplemental_address_1' => '', 'supplemental_address_2' => '', 'city' => '', @@ -119,7 +119,7 @@ function contact_get_expectedresult() { 'state_province_name' => '', 'state_province' => '', 'country' => '', - 'id' => '1', + 'id' => '3', 'api.website.getValue' => 'http://civicrm.org', 'api.Contribution.getCount' => 2, 'api.CustomValue.get' => array( diff --git a/civicrm/api/v3/examples/Contact/APIChainedArrayMultipleCustom.php b/civicrm/api/v3/examples/Contact/APIChainedArrayMultipleCustom.php index c484a896c663c5a18fdc8d37e9f48211d126c4de..d9d6b8f49eed315b8a2c934b23e81ded291c857b 100644 --- a/civicrm/api/v3/examples/Contact/APIChainedArrayMultipleCustom.php +++ b/civicrm/api/v3/examples/Contact/APIChainedArrayMultipleCustom.php @@ -9,7 +9,7 @@ */ function contact_get_example() { $params = array( - 'id' => 1, + 'id' => 3, 'api.website.getValue' => array( 'return' => 'url', ), @@ -48,10 +48,10 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'xyz3, abc3', @@ -87,8 +87,8 @@ function contact_get_expectedresult() { 'sic_code' => '', 'contact_is_deleted' => 0, 'current_employer' => '', - 'address_id' => '2', - 'street_address' => '1 my road', + 'address_id' => '', + 'street_address' => '', 'supplemental_address_1' => '', 'supplemental_address_2' => '', 'city' => '', @@ -116,59 +116,61 @@ function contact_get_expectedresult() { 'state_province_name' => '', 'state_province' => '', 'country' => '', - 'id' => '1', + 'id' => '3', 'api.website.getValue' => 'http://civicrm.org', 'api.Contribution.getCount' => 2, 'api.CustomValue.get' => array( 'is_error' => 0, 'version' => 3, - 'count' => 8, + 'count' => 7, 'values' => array( '0' => array( - 'entity_id' => '1', + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => 'value 4', 'id' => '1', - 'entity_table' => 'Contact', ), '1' => array( + 'entity_id' => '3', 'entity_table' => 'Contact', - ), - '2' => array( - 'entity_id' => '1', 'latest' => 'value 3', 'id' => '2', '1' => 'value 2', - 'entity_table' => 'Contact', '2' => 'value 3', ), - '3' => array( - 'entity_id' => '1', + '2' => array( + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => '', 'id' => '3', '1' => 'warm beer', '2' => '', ), - '4' => array( - 'entity_id' => '1', + '3' => array( + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => '', 'id' => '4', '1' => '', '2' => '', ), - '5' => array( - 'entity_id' => '1', + '4' => array( + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => 'defaultValue', 'id' => '5', '1' => 'defaultValue', ), - '6' => array( - 'entity_id' => '1', + '5' => array( + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => 'vegemite', 'id' => '6', '1' => 'vegemite', ), - '7' => array( - 'entity_id' => '1', + '6' => array( + 'entity_id' => '3', + 'entity_table' => 'Contact', 'latest' => '', 'id' => '7', '1' => '', diff --git a/civicrm/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php b/civicrm/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php index a1b3a68db3a1721f2dca340b08e04a156e4bff21..6bca265586b6a07580e2d29c5694e23008c542fc 100644 --- a/civicrm/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php +++ b/civicrm/api/v3/examples/Contact/APIChainedArrayValuesFromSiblingFunction.php @@ -53,10 +53,10 @@ function contact_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'id' => '1', + '3' => array( + 'id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'do_not_email' => 0, diff --git a/civicrm/api/v3/examples/Contact/ChainTwoWebsites.php b/civicrm/api/v3/examples/Contact/ChainTwoWebsites.php index 8d2a4d3ff54de1e53f0e156b03063f5d053680a9..0c1f887ed412d029d91fddbd3ba81362da828ce6 100644 --- a/civicrm/api/v3/examples/Contact/ChainTwoWebsites.php +++ b/civicrm/api/v3/examples/Contact/ChainTwoWebsites.php @@ -65,10 +65,10 @@ function contact_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'id' => '1', + '3' => array( + 'id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'do_not_email' => 0, @@ -125,7 +125,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'contact_id' => '1', + 'contact_id' => '3', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '1', @@ -165,7 +165,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'contact_id' => '1', + 'contact_id' => '3', 'url' => 'http://civicrm.org', 'website_type_id' => '', ), @@ -179,7 +179,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '2', - 'contact_id' => '1', + 'contact_id' => '3', 'url' => 'http://chained.org', 'website_type_id' => '', ), diff --git a/civicrm/api/v3/examples/Contact/ChainTwoWebsitesSyntax2.php b/civicrm/api/v3/examples/Contact/ChainTwoWebsitesSyntax2.php index 99e6a75588898ffd55ad09393087a6c2518043a6..f6ae673091d10b66f7f37279f5e413a9a520129b 100644 --- a/civicrm/api/v3/examples/Contact/ChainTwoWebsitesSyntax2.php +++ b/civicrm/api/v3/examples/Contact/ChainTwoWebsitesSyntax2.php @@ -68,10 +68,10 @@ function contact_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'id' => '1', + '3' => array( + 'id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'do_not_email' => 0, @@ -128,7 +128,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'contact_id' => '1', + 'contact_id' => '3', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '1', @@ -169,7 +169,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '1', - 'contact_id' => '1', + 'contact_id' => '3', 'url' => 'http://civicrm.org', 'website_type_id' => '', ), @@ -183,7 +183,7 @@ function contact_create_expectedresult() { 'values' => array( '0' => array( 'id' => '2', - 'contact_id' => '1', + 'contact_id' => '3', 'url' => 'http://chained.org', 'website_type_id' => '2', ), diff --git a/civicrm/api/v3/examples/Contact/Create.php b/civicrm/api/v3/examples/Contact/Create.php index 9e0392a4dcdb1eecd8c33bce6f21231fd5814f54..107c95ded389111e7f356d9dc8a3f726a2f90c35 100644 --- a/civicrm/api/v3/examples/Contact/Create.php +++ b/civicrm/api/v3/examples/Contact/Create.php @@ -46,10 +46,10 @@ function contact_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'id' => '1', + '3' => array( + 'id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'do_not_email' => 0, diff --git a/civicrm/api/v3/examples/Contact/CreateParticipantPayment.php b/civicrm/api/v3/examples/Contact/CreateParticipantPayment.php index 80021fa595a1d82b85255114007102dfbccc3c1b..7a66c4277b84121cde4e1269030a122a60d13866 100644 --- a/civicrm/api/v3/examples/Contact/CreateParticipantPayment.php +++ b/civicrm/api/v3/examples/Contact/CreateParticipantPayment.php @@ -13,7 +13,7 @@ function contact_create_example() { 'contact_type' => 'Individual', 'display_name' => 'dlobo', 'api.participant' => array( - 'event_id' => 40, + 'event_id' => 42, 'status_id' => 1, 'role_id' => 1, 'format.only_id' => 1, @@ -38,7 +38,8 @@ function contact_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -73,7 +74,7 @@ function contact_create_expectedresult() { 'is_opt_out' => 0, 'legal_identifier' => '', 'external_identifier' => '', - 'sort_name' => '', + 'sort_name' => 'dlobo', 'display_name' => 'dlobo', 'nick_name' => '', 'legal_name' => '', diff --git a/civicrm/api/v3/examples/Contact/CustomFieldGet.php b/civicrm/api/v3/examples/Contact/CustomFieldGet.php index ac3e7b3ab680e3b414474c874456e90bda1c4a96..07e8ae1e6e6ed9970a952f5481f3a16d83ebd78b 100644 --- a/civicrm/api/v3/examples/Contact/CustomFieldGet.php +++ b/civicrm/api/v3/examples/Contact/CustomFieldGet.php @@ -10,7 +10,7 @@ function contact_get_example() { $params = array( 'return.custom_1' => 1, - 'id' => 1, + 'id' => 3, ); try{ @@ -44,13 +44,13 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'civicrm_value_testgetwithcu_1_id' => '1', 'custom_1' => 'custom string', - 'id' => '1', + 'id' => '3', ), ), ); diff --git a/civicrm/api/v3/examples/Contact/CustomFieldGetReturnSyntaxVariation.php b/civicrm/api/v3/examples/Contact/CustomFieldGetReturnSyntaxVariation.php index d5ac755842aa09050b34466c93581fc091e805cd..c1e47702bff5f10dd82092acd931ab33160b747d 100644 --- a/civicrm/api/v3/examples/Contact/CustomFieldGetReturnSyntaxVariation.php +++ b/civicrm/api/v3/examples/Contact/CustomFieldGetReturnSyntaxVariation.php @@ -10,7 +10,7 @@ function contact_get_example() { $params = array( 'return' => 'custom_1', - 'id' => 1, + 'id' => 3, ); try{ @@ -44,13 +44,13 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'civicrm_value_testgetwithcu_1_id' => '1', 'custom_1' => 'custom string', - 'id' => '1', + 'id' => '3', ), ), ); diff --git a/civicrm/api/v3/examples/Contact/Delete.php b/civicrm/api/v3/examples/Contact/Delete.php index bfb4f9976e7ee61789f5316fa1b3d39138ec0f44..1bb7f83feb3e21c2eea3bbc3f45bc60e84626884 100644 --- a/civicrm/api/v3/examples/Contact/Delete.php +++ b/civicrm/api/v3/examples/Contact/Delete.php @@ -7,7 +7,7 @@ */ function contact_delete_example() { $params = array( - 'id' => 1, + 'id' => 3, ); try{ diff --git a/civicrm/api/v3/examples/Contact/Get.php b/civicrm/api/v3/examples/Contact/Get.php index fb2556c9f48cc35b58d955ab7eaa89bbfbecb95b..9f666711fc9bdd632ca0cdf02ba2282bc5f3791e 100644 --- a/civicrm/api/v3/examples/Contact/Get.php +++ b/civicrm/api/v3/examples/Contact/Get.php @@ -41,10 +41,10 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'man2@yahoo.com', @@ -80,8 +80,8 @@ function contact_get_expectedresult() { 'sic_code' => '', 'contact_is_deleted' => 0, 'current_employer' => '', - 'address_id' => '2', - 'street_address' => '1 my road', + 'address_id' => '', + 'street_address' => '', 'supplemental_address_1' => '', 'supplemental_address_2' => '', 'city' => '', @@ -109,7 +109,7 @@ function contact_get_expectedresult() { 'state_province_name' => '', 'state_province' => '', 'country' => '', - 'id' => '1', + 'id' => '3', ), ), ); diff --git a/civicrm/api/v3/examples/Contact/GetActions.php b/civicrm/api/v3/examples/Contact/GetActions.php index d2c85713ed1ceecc4735db3475a133f495667b2a..585e5e8dca83137190c6126b0b619d2837f1ad06 100644 --- a/civicrm/api/v3/examples/Contact/GetActions.php +++ b/civicrm/api/v3/examples/Contact/GetActions.php @@ -40,33 +40,28 @@ function contact_getactions_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 25, + 'count' => 20, 'values' => array( '0' => 'create', '1' => 'delete', '2' => 'duplicatecheck', - '3' => 'example_action1', - '4' => 'example_action2', - '5' => 'get', - '6' => 'getactions', - '7' => 'getcount', - '8' => 'getfield', - '9' => 'getfields', - '10' => 'getlist', - '11' => 'getoptions', - '12' => 'getquick', - '13' => 'getrefcount', - '14' => 'getsingle', - '15' => 'getvalue', - '16' => 'merge', - '17' => 'proximity', - '18' => 'replace', - '19' => 'setvalue', - '20' => 'type_create', - '21' => 'type_delete', - '22' => 'type_get', - '23' => 'update', - '24' => 'validate', + '3' => 'get', + '4' => 'getactions', + '5' => 'getcount', + '6' => 'getfield', + '7' => 'getfields', + '8' => 'getlist', + '9' => 'getoptions', + '10' => 'getquick', + '11' => 'getrefcount', + '12' => 'getsingle', + '13' => 'getvalue', + '14' => 'merge', + '15' => 'proximity', + '16' => 'replace', + '17' => 'setvalue', + '18' => 'update', + '19' => 'validate', ), 'deprecated' => array( 'getquick' => 'The "getquick" action is deprecated in favor of "getlist".', diff --git a/civicrm/api/v3/examples/Contact/GetFieldsOptions.php b/civicrm/api/v3/examples/Contact/GetFieldsOptions.php index a366b409581927430b2af1fc223f863acd32e78b..57972c52525932146d426b8efb3f28adc51895f1 100644 --- a/civicrm/api/v3/examples/Contact/GetFieldsOptions.php +++ b/civicrm/api/v3/examples/Contact/GetFieldsOptions.php @@ -57,6 +57,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.id', 'headerPattern' => '/internal|contact?|id$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'api.aliases' => array( '0' => 'contact_id', ), @@ -70,6 +73,9 @@ function contact_getfields_expectedresult() { 'size' => 30, 'export' => TRUE, 'where' => 'civicrm_contact.contact_type', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'maxlength' => 64, @@ -94,6 +100,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.contact_sub_type', 'headerPattern' => '/C(ontact )?(subtype|sub-type|sub type)/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'maxlength' => 255, @@ -115,6 +124,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/d(o )?(not )?(email)/i', 'dataPattern' => '/^\\d{1,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -128,6 +140,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/d(o )?(not )?(call|phone)/i', 'dataPattern' => '/^\\d{1,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -141,6 +156,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^(d(o\\s)?n(ot\\s)?mail)|(\\w*)?bulk\\s?(\\w*)$/i', 'dataPattern' => '/^\\d{1,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -154,6 +172,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/d(o )?(not )?(sms)/i', 'dataPattern' => '/^\\d{1,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -167,6 +188,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/d(o )?(not )?(trade)/i', 'dataPattern' => '/^\\d{1,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -180,6 +204,9 @@ function contact_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_contact.is_opt_out', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -197,6 +224,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/legal\\s?id/i', 'dataPattern' => '/\\w+?\\d{5,}/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 32, @@ -215,6 +245,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/external\\s?id/i', 'dataPattern' => '/^\\d{11,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -230,6 +263,9 @@ function contact_getfields_expectedresult() { 'size' => 30, 'export' => TRUE, 'where' => 'civicrm_contact.sort_name', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -245,6 +281,9 @@ function contact_getfields_expectedresult() { 'size' => 30, 'export' => TRUE, 'where' => 'civicrm_contact.display_name', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -263,6 +302,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/n(ick\\s)name|nick$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -280,6 +322,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.legal_name', 'headerPattern' => '/^legal|(l(egal\\s)?name)$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -294,6 +339,9 @@ function contact_getfields_expectedresult() { 'import' => TRUE, 'where' => 'civicrm_contact.image_URL', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'File', 'rows' => 2, @@ -312,6 +360,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^p(ref\\w*\\s)?c(omm\\w*)|( meth\\w*)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'maxlength' => 255, @@ -333,6 +384,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.preferred_language', 'headerPattern' => '/^lang/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'maxlength' => 5, @@ -356,6 +410,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^p(ref\\w*\\s)?m(ail\\s)?f(orm\\w*)$/i', 'export' => TRUE, 'default' => 'Both', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'maxlength' => 8, @@ -374,6 +431,9 @@ function contact_getfields_expectedresult() { 'size' => 20, 'export' => TRUE, 'where' => 'civicrm_contact.hash', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'api_key' => array( 'name' => 'api_key', @@ -382,6 +442,9 @@ function contact_getfields_expectedresult() { 'description' => 'API Key for validating requests related to this contact.', 'maxlength' => 32, 'size' => 20, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'first_name' => array( 'name' => 'first_name', @@ -395,6 +458,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^first|(f(irst\\s)?name)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -413,6 +479,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^middle|(m(iddle\\s)?name)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -431,6 +500,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^last|(l(ast\\s)?name)$/i', 'dataPattern' => '/^\\w+(\\s\\w+)?+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -447,6 +519,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^(prefix|title)/i', 'dataPattern' => '/^(mr|ms|mrs|sir|dr)\\.?$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -471,6 +546,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^suffix$/i', 'dataPattern' => '/^(sr|jr)\\.?|i{2,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -496,6 +574,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.formal_title', 'headerPattern' => '/^title/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 64, @@ -509,6 +590,9 @@ function contact_getfields_expectedresult() { 'description' => 'Communication style (e.g. formal vs. familiar) to use with this contact. FK to communication styles in civicrm_option_value.', 'export' => TRUE, 'where' => 'civicrm_contact.communication_style_id', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -524,6 +608,9 @@ function contact_getfields_expectedresult() { 'type' => 1, 'title' => 'Email Greeting ID', 'description' => 'FK to civicrm_option_value.id, that has to be valid registered Email Greeting.', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'email_greeting_custom' => array( 'name' => 'email_greeting_custom', @@ -534,6 +621,9 @@ function contact_getfields_expectedresult() { 'size' => 45, 'import' => TRUE, 'where' => 'civicrm_contact.email_greeting_custom', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -547,6 +637,9 @@ function contact_getfields_expectedresult() { 'description' => 'Cache Email Greeting.', 'maxlength' => 255, 'size' => 45, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -558,6 +651,9 @@ function contact_getfields_expectedresult() { 'type' => 1, 'title' => 'Postal Greeting ID', 'description' => 'FK to civicrm_option_value.id, that has to be valid registered Postal Greeting.', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'size' => 6, @@ -573,6 +669,9 @@ function contact_getfields_expectedresult() { 'size' => 45, 'import' => TRUE, 'where' => 'civicrm_contact.postal_greeting_custom', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -586,6 +685,9 @@ function contact_getfields_expectedresult() { 'description' => 'Cache Postal greeting.', 'maxlength' => 255, 'size' => 45, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -597,6 +699,9 @@ function contact_getfields_expectedresult() { 'type' => 1, 'title' => 'Addressee ID', 'description' => 'FK to civicrm_option_value.id, that has to be valid registered Addressee.', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'addressee_custom' => array( 'name' => 'addressee_custom', @@ -607,6 +712,9 @@ function contact_getfields_expectedresult() { 'size' => 45, 'import' => TRUE, 'where' => 'civicrm_contact.addressee_custom', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -620,6 +728,9 @@ function contact_getfields_expectedresult() { 'description' => 'Cache Addressee.', 'maxlength' => 255, 'size' => 45, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -638,6 +749,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^job|(j(ob\\s)?title)$/i', 'dataPattern' => '//', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -653,6 +767,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.gender_id', 'headerPattern' => '/^gender$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select', 'size' => 6, @@ -676,8 +793,12 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^birth|(b(irth\\s)?date)|D(\\W*)O(\\W*)B(\\W*)$/i', 'dataPattern' => '/\\d{4}-?\\d{2}-?\\d{2}/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select Date', + 'format' => 'birth', ), ), 'is_deceased' => array( @@ -688,6 +809,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.is_deceased', 'headerPattern' => '/i(s\\s)?d(eceased)$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -701,8 +825,12 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.deceased_date', 'headerPattern' => '/^deceased|(d(eceased\\s)?date)$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Select Date', + 'format' => 'birth', ), ), 'household_name' => array( @@ -717,6 +845,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^household|(h(ousehold\\s)?name)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -728,6 +859,9 @@ function contact_getfields_expectedresult() { 'type' => 1, 'title' => 'Household Primary Contact ID', 'description' => 'Optional FK to Primary Contact for this household.', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'html' => array( 'type' => 'Select', @@ -748,6 +882,9 @@ function contact_getfields_expectedresult() { 'headerPattern' => '/^organization|(o(rganization\\s)?name)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 128, @@ -765,6 +902,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.sic_code', 'headerPattern' => '/^sic|(s(ic\\s)?code)$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 8, @@ -784,6 +924,9 @@ function contact_getfields_expectedresult() { 'dataPattern' => '/^[\\w\\/\\:\\.]+$/', 'export' => TRUE, 'rule' => 'url', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -799,6 +942,9 @@ function contact_getfields_expectedresult() { 'export' => TRUE, 'where' => 'civicrm_contact.created_date', 'default' => 'NULL', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'modified_date' => array( 'name' => 'modified_date', @@ -809,6 +955,9 @@ function contact_getfields_expectedresult() { 'export' => TRUE, 'where' => 'civicrm_contact.modified_date', 'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', ), 'source' => array( 'name' => 'source', @@ -821,6 +970,9 @@ function contact_getfields_expectedresult() { 'where' => 'civicrm_contact.source', 'headerPattern' => '/(C(ontact\\s)?Source)$/i', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', 'maxlength' => 255, @@ -835,6 +987,9 @@ function contact_getfields_expectedresult() { 'description' => 'OPTIONAL FK to civicrm_contact record.', 'export' => TRUE, 'where' => 'civicrm_contact.employer_id', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'html' => array( 'type' => 'EntityRef', @@ -851,6 +1006,9 @@ function contact_getfields_expectedresult() { 'required' => TRUE, 'export' => TRUE, 'where' => 'civicrm_contact.is_deleted', + 'table_name' => 'civicrm_contact', + 'entity' => 'Contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'CheckBox', ), @@ -878,8 +1036,8 @@ function contact_getfields_expectedresult() { 'table_name' => 'civicrm_value_select_test_g_1', 'column_name' => 'our_special_field_1', 'pseudoconstant' => array( - 'optionGroupName' => 'our_special_field_20170124082923', - 'optionEditPath' => 'civicrm/admin/options/our_special_field_20170124082923', + 'optionGroupName' => 'our_special_field_20170207021937', + 'optionEditPath' => 'civicrm/admin/options/our_special_field_20170207021937', ), 'name' => 'custom_1', 'title' => 'Our special field', diff --git a/civicrm/api/v3/examples/Contact/GroupFilterUsingContactAPI.php b/civicrm/api/v3/examples/Contact/GroupFilterUsingContactAPI.php index 67fadede7a07462b5e25dedd741c532a5745e1a2..879b059fa5537f822b5fde8031a0068647f7ce9e 100644 --- a/civicrm/api/v3/examples/Contact/GroupFilterUsingContactAPI.php +++ b/civicrm/api/v3/examples/Contact/GroupFilterUsingContactAPI.php @@ -9,11 +9,12 @@ */ function contact_get_example() { $params = array( - 'filter.group_id' => array( - '0' => 1, - '1' => 26, + 'group' => array( + 'IN' => array( + '0' => 'Test group C', + '1' => 'Test group D', + ), ), - 'contact_type' => 'Individual', ); try{ @@ -47,14 +48,14 @@ function contact_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 3, 'values' => array( - '1' => array( - 'contact_id' => '1', + '3' => array( + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', - 'sort_name' => 'man2@yahoo.com', - 'display_name' => 'man2@yahoo.com', + 'sort_name' => 'Groupmember, Test2', + 'display_name' => 'Test2 Groupmember', 'do_not_email' => 0, 'do_not_phone' => 0, 'do_not_mail' => 0, @@ -69,9 +70,9 @@ function contact_get_expectedresult() { 'preferred_communication_method' => '', 'preferred_language' => 'en_US', 'preferred_mail_format' => 'Both', - 'first_name' => '', + 'first_name' => 'Test2', 'middle_name' => '', - 'last_name' => '', + 'last_name' => 'Groupmember', 'prefix_id' => '', 'suffix_id' => '', 'formal_title' => '', @@ -86,8 +87,8 @@ function contact_get_expectedresult() { 'sic_code' => '', 'contact_is_deleted' => 0, 'current_employer' => '', - 'address_id' => '2', - 'street_address' => '1 my road', + 'address_id' => '', + 'street_address' => '', 'supplemental_address_1' => '', 'supplemental_address_2' => '', 'city' => '', @@ -101,7 +102,7 @@ function contact_get_expectedresult() { 'phone_type_id' => '', 'phone' => '', 'email_id' => '1', - 'email' => 'man2@yahoo.com', + 'email' => 'test@example.org', 'on_hold' => 0, 'im_id' => '', 'provider_id' => '', @@ -115,7 +116,7 @@ function contact_get_expectedresult() { 'state_province_name' => '', 'state_province' => '', 'country' => '', - 'id' => '1', + 'id' => '3', ), ), ); @@ -125,7 +126,7 @@ function contact_get_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testGetGroupIDFromContact" +* The test that created it is called "testContactGetWithGroupTitleMultipleGroups" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContactTest.php * diff --git a/civicrm/api/v3/examples/Contribution/ContributionCreateWithHonoreeContact.php b/civicrm/api/v3/examples/Contribution/ContributionCreateWithHonoreeContact.php index fe6ec8ee0965bb9f6da8fbf60eb5e5111c5a4a33..0ed270153050d214d61279657712a169de9eeacd 100644 --- a/civicrm/api/v3/examples/Contribution/ContributionCreateWithHonoreeContact.php +++ b/civicrm/api/v3/examples/Contribution/ContributionCreateWithHonoreeContact.php @@ -9,7 +9,7 @@ */ function contribution_create_example() { $params = array( - 'contact_id' => 23, + 'contact_id' => 28, 'receive_date' => '20120511', 'total_amount' => '100', 'financial_type_id' => 1, @@ -18,7 +18,7 @@ function contribution_create_example() { 'net_amount' => '95', 'source' => 'SSF', 'contribution_status_id' => 1, - 'honor_contact_id' => 24, + 'honor_contact_id' => 29, ); try{ @@ -30,7 +30,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -55,7 +56,7 @@ function contribution_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '23', + 'contact_id' => '28', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', @@ -82,6 +83,7 @@ function contribution_create_expectedresult() { 'campaign_id' => '', 'creditnote_id' => '', 'tax_amount' => '', + 'revenue_recognition_date' => '', 'contribution_type_id' => '1', ), ), diff --git a/civicrm/api/v3/examples/Contribution/ContributionCreateWithNote.php b/civicrm/api/v3/examples/Contribution/ContributionCreateWithNote.php index 4a19762036ba1bc554ec2c46587aa2fe201b9b6c..394b0c36ada2a4d1a1700b253afc594e5da44103 100644 --- a/civicrm/api/v3/examples/Contribution/ContributionCreateWithNote.php +++ b/civicrm/api/v3/examples/Contribution/ContributionCreateWithNote.php @@ -9,7 +9,7 @@ */ function contribution_create_example() { $params = array( - 'contact_id' => 17, + 'contact_id' => 22, 'receive_date' => '2012-01-01', 'total_amount' => '100', 'financial_type_id' => 1, @@ -33,7 +33,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -58,7 +59,7 @@ function contribution_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '17', + 'contact_id' => '22', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '1', @@ -85,6 +86,7 @@ function contribution_create_expectedresult() { 'campaign_id' => '', 'creditnote_id' => '', 'tax_amount' => '', + 'revenue_recognition_date' => '', 'contribution_type_id' => '1', ), ), diff --git a/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCredit.php b/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCredit.php index f756efed96d3a6ae173e61c0402dda2fdc13ec3e..a798c940b10f96510fbd7cf23ae5b1229f3b717e 100644 --- a/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCredit.php +++ b/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCredit.php @@ -9,7 +9,7 @@ */ function contribution_create_example() { $params = array( - 'contact_id' => 19, + 'contact_id' => 24, 'receive_date' => '20120511', 'total_amount' => '100', 'financial_type_id' => 1, @@ -20,7 +20,7 @@ function contribution_create_example() { 'contribution_status_id' => 1, 'soft_credit' => array( '1' => array( - 'contact_id' => 20, + 'contact_id' => 25, 'amount' => 50, 'soft_credit_type_id' => 3, ), @@ -36,7 +36,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -61,7 +62,7 @@ function contribution_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '19', + 'contact_id' => '24', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', @@ -88,6 +89,7 @@ function contribution_create_expectedresult() { 'campaign_id' => '', 'creditnote_id' => '', 'tax_amount' => '', + 'revenue_recognition_date' => '', 'contribution_type_id' => '1', ), ), diff --git a/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCreditDefaults.php b/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCreditDefaults.php index 8d7126cb897de7c0f5218e7f9f9b630623beca52..5209aa9aea94479b470d6f89333a9ba6d7eaaa22 100644 --- a/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCreditDefaults.php +++ b/civicrm/api/v3/examples/Contribution/ContributionCreateWithSoftCreditDefaults.php @@ -9,7 +9,7 @@ */ function contribution_create_example() { $params = array( - 'contact_id' => 21, + 'contact_id' => 26, 'receive_date' => '20120511', 'total_amount' => '100', 'financial_type_id' => 1, @@ -18,7 +18,7 @@ function contribution_create_example() { 'net_amount' => '95', 'source' => 'SSF', 'contribution_status_id' => 1, - 'soft_credit_to' => 22, + 'soft_credit_to' => 27, ); try{ @@ -30,7 +30,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -55,7 +56,7 @@ function contribution_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '21', + 'contact_id' => '26', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', @@ -82,6 +83,7 @@ function contribution_create_expectedresult() { 'campaign_id' => '', 'creditnote_id' => '', 'tax_amount' => '', + 'revenue_recognition_date' => '', 'contribution_type_id' => '1', ), ), diff --git a/civicrm/api/v3/examples/Contribution/Create.php b/civicrm/api/v3/examples/Contribution/Create.php index 9135fe3f9201247b95e9ff1e0b4cbbfca8d92269..9b4997039319cd65ec4e8eadd6a731a094b87a64 100644 --- a/civicrm/api/v3/examples/Contribution/Create.php +++ b/civicrm/api/v3/examples/Contribution/Create.php @@ -13,6 +13,7 @@ function contribution_create_example() { 'financial_type_id' => 1, 'contribution_page_id' => 1, 'trxn_id' => 12345, + 'is_pay_later' => 1, 'invoice_id' => 67890, 'source' => 'SSF', 'contribution_status_id' => 2, @@ -27,7 +28,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -59,7 +61,7 @@ function contribution_create_expectedresult() { 'receive_date' => '20120511000000', 'non_deductible_amount' => '', 'total_amount' => '100', - 'fee_amount' => '0', + 'fee_amount' => 0, 'net_amount' => '100', 'trxn_id' => '12345', 'invoice_id' => '67890', @@ -72,15 +74,15 @@ function contribution_create_expectedresult() { 'amount_level' => '', 'contribution_recur_id' => '', 'is_test' => '', - 'is_pay_later' => '', + 'is_pay_later' => '1', 'contribution_status_id' => '2', 'address_id' => '', 'check_number' => '', 'campaign_id' => '', 'creditnote_id' => '', 'tax_amount' => '', - 'contribution_type_id' => '1', 'revenue_recognition_date' => '', + 'contribution_type_id' => '1', ), ), ); @@ -90,9 +92,9 @@ function contribution_create_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testCreateContributionPendingOnline" +* The test that created it is called "testCreateContributionPayLaterOnline" * and can be found at: -* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/TaxContributionPageTest.php +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionTest.php * * You can see the outcome of the API tests at * https://test.civicrm.org/job/CiviCRM-master-git/ diff --git a/civicrm/api/v3/examples/Contribution/CreateWithNestedLineItems.php b/civicrm/api/v3/examples/Contribution/CreateWithNestedLineItems.php index 2c7234e41960bd60f593ba2c0930633821c4eb66..741e1763979750fe7d6a16188a4c9a372346f20d 100644 --- a/civicrm/api/v3/examples/Contribution/CreateWithNestedLineItems.php +++ b/civicrm/api/v3/examples/Contribution/CreateWithNestedLineItems.php @@ -9,10 +9,14 @@ */ function contribution_create_example() { $params = array( - 'contact_id' => 1, + 'contact_id' => 11, 'receive_date' => '20120511', - 'total_amount' => '400', - 'financial_type_id' => 7, + 'total_amount' => '100', + 'financial_type_id' => 1, + 'payment_instrument_id' => 1, + 'non_deductible_amount' => '10', + 'fee_amount' => '50', + 'net_amount' => '90', 'trxn_id' => 12345, 'invoice_id' => 67890, 'source' => 'SSF', @@ -20,22 +24,16 @@ function contribution_create_example() { 'skipLineItem' => 1, 'api.line_item.create' => array( '0' => array( - 'price_field_id' => array( - '0' => 3, - ), - 'qty' => 1, - 'line_total' => '100', - 'unit_price' => '100', - 'financial_type_id' => 7, + 'price_field_id' => 1, + 'qty' => 2, + 'line_total' => '20', + 'unit_price' => '10', ), '1' => array( - 'price_field_id' => array( - '0' => 3, - ), + 'price_field_id' => 1, 'qty' => 1, - 'line_total' => '300', - 'unit_price' => '300', - 'financial_type_id' => 8, + 'line_total' => '80', + 'unit_price' => '80', ), ), ); @@ -49,7 +47,8 @@ function contribution_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -74,15 +73,15 @@ function contribution_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '1', - 'financial_type_id' => '7', + 'contact_id' => '11', + 'financial_type_id' => '1', 'contribution_page_id' => '', - 'payment_instrument_id' => '4', + 'payment_instrument_id' => '1', 'receive_date' => '20120511000000', - 'non_deductible_amount' => '', - 'total_amount' => '435', - 'fee_amount' => 0, - 'net_amount' => '435', + 'non_deductible_amount' => '10', + 'total_amount' => '100', + 'fee_amount' => '50', + 'net_amount' => '90', 'trxn_id' => '12345', 'invoice_id' => '67890', 'currency' => 'USD', @@ -100,8 +99,9 @@ function contribution_create_expectedresult() { 'check_number' => '', 'campaign_id' => '', 'creditnote_id' => '', - 'tax_amount' => '35', - 'contribution_type_id' => '7', + 'tax_amount' => 0, + 'revenue_recognition_date' => '', + 'contribution_type_id' => '1', 'api.line_item.create' => array( '0' => array( 'is_error' => 0, @@ -114,18 +114,16 @@ function contribution_create_expectedresult() { 'entity_table' => 'civicrm_contribution', 'entity_id' => '1', 'contribution_id' => '1', - 'price_field_id' => array( - '0' => '3', - ), + 'price_field_id' => '1', 'label' => 'line item', - 'qty' => '1', - 'unit_price' => '100', - 'line_total' => '100', + 'qty' => '2', + 'unit_price' => '10', + 'line_total' => '20', 'participant_count' => '', 'price_field_value_id' => '', - 'financial_type_id' => '7', - 'deductible_amount' => '', - 'tax_amount' => '20', + 'financial_type_id' => '', + 'non_deductible_amount' => '', + 'tax_amount' => '', ), ), ), @@ -140,18 +138,16 @@ function contribution_create_expectedresult() { 'entity_table' => 'civicrm_contribution', 'entity_id' => '1', 'contribution_id' => '1', - 'price_field_id' => array( - '0' => '3', - ), + 'price_field_id' => '1', 'label' => 'line item', 'qty' => '1', - 'unit_price' => '300', - 'line_total' => '300', + 'unit_price' => '80', + 'line_total' => '80', 'participant_count' => '', 'price_field_value_id' => '', - 'financial_type_id' => '8', - 'deductible_amount' => '', - 'tax_amount' => '15', + 'financial_type_id' => '', + 'non_deductible_amount' => '', + 'tax_amount' => '', ), ), ), @@ -167,7 +163,7 @@ function contribution_create_expectedresult() { * This example has been generated from the API test suite. * The test that created it is called "testCreateContributionChainedLineItems" * and can be found at: -* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/TaxContributionPageTest.php +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionTest.php * * You can see the outcome of the API tests at * https://test.civicrm.org/job/CiviCRM-master-git/ diff --git a/civicrm/api/v3/examples/Contribution/Delete.php b/civicrm/api/v3/examples/Contribution/Delete.php index 0242584211948b8bebf064b1001ca75c115a69f0..c22b1b102d2219623ce027337592c4b5ae5fc69f 100644 --- a/civicrm/api/v3/examples/Contribution/Delete.php +++ b/civicrm/api/v3/examples/Contribution/Delete.php @@ -19,7 +19,8 @@ function contribution_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -53,7 +54,7 @@ function contribution_delete_expectedresult() { * This example has been generated from the API test suite. * The test that created it is called "testDeleteContribution" * and can be found at: -* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/TaxContributionPageTest.php +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionTest.php * * You can see the outcome of the API tests at * https://test.civicrm.org/job/CiviCRM-master-git/ diff --git a/civicrm/api/v3/examples/Contribution/Get.php b/civicrm/api/v3/examples/Contribution/Get.php index 3649403beaa74b45d8ac2445d60e2b0e523b7187..0c5c06f58f2f04481605f20ec4e5a02f10530337 100644 --- a/civicrm/api/v3/examples/Contribution/Get.php +++ b/civicrm/api/v3/examples/Contribution/Get.php @@ -19,7 +19,8 @@ function contribution_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -43,7 +44,7 @@ function contribution_get_expectedresult() { 'id' => 1, 'values' => array( '1' => array( - 'contact_id' => '4', + 'contact_id' => '3', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'sort_name' => 'Anderson, Anthony', @@ -63,10 +64,11 @@ function contribution_get_expectedresult() { 'thankyou_date' => '', 'contribution_source' => 'SSF', 'amount_level' => '', + 'contribution_recur_id' => '', 'is_test' => 0, 'is_pay_later' => 0, 'contribution_status_id' => '1', - 'check_number' => '', + 'contribution_check_number' => '', 'contribution_campaign_id' => '', 'financial_type_id' => '1', 'financial_type' => 'Donation', @@ -78,16 +80,17 @@ function contribution_get_expectedresult() { 'fulfilled_date' => '', 'contribution_start_date' => '', 'contribution_end_date' => '', - 'contribution_recur_id' => '', 'financial_account_id' => '1', 'accounting_code' => '4200', + 'campaign_id' => '', + 'contribution_campaign_title' => '', 'contribution_note' => '', 'contribution_batch' => '', 'contribution_status' => 'Completed', 'payment_instrument' => 'Check', 'payment_instrument_id' => '4', 'instrument_id' => '4', - 'contribution_check_number' => '', + 'check_number' => '', 'id' => '1', 'contribution_type_id' => '1', ), @@ -99,7 +102,7 @@ function contribution_get_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testGetContributionLegacyBehaviour" +* The test that created it is called "testGetContribution" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionTest.php * diff --git a/civicrm/api/v3/examples/ContributionPage/Create.php b/civicrm/api/v3/examples/ContributionPage/Create.php index bff46b83dedcecba07fae741c0264d5eefd665a7..8139aa301a4e42e16d11f01503aca666b5bed2eb 100644 --- a/civicrm/api/v3/examples/ContributionPage/Create.php +++ b/civicrm/api/v3/examples/ContributionPage/Create.php @@ -13,6 +13,9 @@ function contribution_page_create_example() { 'goal_amount' => 34567, 'is_pay_later' => 1, 'is_monetary' => TRUE, + 'is_email_receipt' => TRUE, + 'receipt_from_email' => 'yourconscience@donate.com', + 'receipt_from_name' => 'Ego Freud', ); try{ @@ -77,11 +80,9 @@ function contribution_page_create_expectedresult() { 'thankyou_title' => '', 'thankyou_text' => '', 'thankyou_footer' => '', - 'is_for_organization' => '', - 'for_organization' => '', - 'is_email_receipt' => '', - 'receipt_from_name' => '', - 'receipt_from_email' => '', + 'is_email_receipt' => '1', + 'receipt_from_name' => 'Ego Freud', + 'receipt_from_email' => 'yourconscience@donate.com', 'cc_receipt' => '', 'bcc_receipt' => '', 'receipt_text' => '', diff --git a/civicrm/api/v3/examples/ContributionPage/Get.php b/civicrm/api/v3/examples/ContributionPage/Get.php index cc7cd888b2ee99f03f3f9c2184316e9dded66cef..0a6b234e907ec8f5066f488f1e2754c78f2525f0 100644 --- a/civicrm/api/v3/examples/ContributionPage/Get.php +++ b/civicrm/api/v3/examples/ContributionPage/Get.php @@ -7,7 +7,6 @@ */ function contribution_page_get_example() { $params = array( - 'amount' => '34567', 'currency' => 'NZD', 'financial_type_id' => 1, ); @@ -55,17 +54,20 @@ function contribution_page_get_expectedresult() { 'is_confirm_enabled' => '1', 'is_recur_interval' => 0, 'is_recur_installments' => 0, + 'adjust_recur_start_date' => 0, 'is_pay_later' => '1', 'is_partial_payment' => 0, 'is_allow_other_amount' => 0, 'goal_amount' => '34567.00', - 'is_for_organization' => 0, - 'is_email_receipt' => 0, + 'is_email_receipt' => '1', + 'receipt_from_name' => 'Ego Freud', + 'receipt_from_email' => 'yourconscience@donate.com', 'is_active' => '1', 'amount_block_is_active' => '1', 'currency' => 'NZD', 'is_share' => '1', 'is_billing_required' => 0, + 'contribution_type_id' => '1', ), ), ); @@ -75,7 +77,7 @@ function contribution_page_get_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testGetContributionPageByAmount" +* The test that created it is called "testGetBasicContributionPage" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionPageTest.php * diff --git a/civicrm/api/v3/examples/ContributionPage/Submit.php b/civicrm/api/v3/examples/ContributionPage/Submit.php index db56853f5d57ec3f0709b0b2b6aaca621ed5b237..c24c4dbcb3934d62c01380acb0cb23960e4151da 100644 --- a/civicrm/api/v3/examples/ContributionPage/Submit.php +++ b/civicrm/api/v3/examples/ContributionPage/Submit.php @@ -9,16 +9,14 @@ */ function contribution_page_submit_example() { $params = array( - 'price_3' => '', 'id' => 1, - 'amount' => 10, + 'pledge_amount' => array( + '2' => 1, + ), 'billing_first_name' => 'Billy', 'billing_middle_name' => 'Goat', 'billing_last_name' => 'Gruff', 'email' => 'billy@goat.gruff', - 'selectMembership' => array( - '0' => 1, - ), 'payment_processor_id' => 1, 'credit_card_number' => '4111111111111111', 'credit_card_type' => 'Visa', @@ -27,9 +25,12 @@ function contribution_page_submit_example() { 'Y' => 2040, ), 'cvv2' => 123, - 'is_recur' => 1, - 'frequency_interval' => 1, - 'frequency_unit' => 'month', + 'pledge_id' => '1', + 'cid' => '77', + 'contact_id' => '77', + 'amount' => '100', + 'is_pledge' => TRUE, + 'pledge_block_id' => 2, ); try{ @@ -71,7 +72,7 @@ function contribution_page_submit_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed" +* The test that created it is called "testSubmitPledgePayment" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionPageTest.php * diff --git a/civicrm/api/v3/examples/ContributionRecur/Delete.php b/civicrm/api/v3/examples/ContributionRecur/Delete.php index f5b732f6f0f57ee27a320d0aac9214e46cc896a4..fba4f0585044d1bb82c40d67f66c061b1c22574d 100644 --- a/civicrm/api/v3/examples/ContributionRecur/Delete.php +++ b/civicrm/api/v3/examples/ContributionRecur/Delete.php @@ -7,7 +7,7 @@ */ function contribution_recur_delete_example() { $params = array( - 'id' => 3, + 'id' => 4, ); try{ diff --git a/civicrm/api/v3/examples/Country/Create.php b/civicrm/api/v3/examples/Country/Create.php index 091baaa5ef9e651c16e848bbc006597c4fc6093a..988b9bcfc9158c3b8a5ec4f29d5e9242623043d8 100644 --- a/civicrm/api/v3/examples/Country/Create.php +++ b/civicrm/api/v3/examples/Country/Create.php @@ -43,10 +43,10 @@ function country_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1252, + 'id' => 1254, 'values' => array( - '1252' => array( - 'id' => '1252', + '1254' => array( + 'id' => '1254', 'name' => 'Made Up Land', 'iso_code' => 'ZZ', 'country_code' => '', diff --git a/civicrm/api/v3/examples/Country/Delete.php b/civicrm/api/v3/examples/Country/Delete.php index a631c34a07baf68d8ab5dd5f2f3a172bd9890482..79fcb15348a4d63e1086bffc6bc9c23d83435b37 100644 --- a/civicrm/api/v3/examples/Country/Delete.php +++ b/civicrm/api/v3/examples/Country/Delete.php @@ -7,7 +7,7 @@ */ function country_delete_example() { $params = array( - 'id' => 1253, + 'id' => 1255, ); try{ diff --git a/civicrm/api/v3/examples/Country/Get.php b/civicrm/api/v3/examples/Country/Get.php index d1cf00f99cdb3e26c33bc496fb6e63879eadc8de..dcd4d4431e8c707f23eb0d97179c09a087196c2b 100644 --- a/civicrm/api/v3/examples/Country/Get.php +++ b/civicrm/api/v3/examples/Country/Get.php @@ -41,10 +41,10 @@ function country_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1254, + 'id' => 1256, 'values' => array( - '1254' => array( - 'id' => '1254', + '1256' => array( + 'id' => '1256', 'name' => 'Made Up Land', 'iso_code' => 'ZZ', 'region_id' => '1', diff --git a/civicrm/api/v3/examples/EntityTag/Delete.php b/civicrm/api/v3/examples/EntityTag/Delete.php index 9d117d4b9bb7b911880be192a9f27d7b3bba1ec0..83d812b1bfc975af24f6354fde4f14e169704984 100644 --- a/civicrm/api/v3/examples/EntityTag/Delete.php +++ b/civicrm/api/v3/examples/EntityTag/Delete.php @@ -7,8 +7,8 @@ */ function entity_tag_delete_example() { $params = array( - 'contact_id_h' => 37, - 'tag_id' => '17', + 'contact_id_h' => 31, + 'tag_id' => '15', ); try{ diff --git a/civicrm/api/v3/examples/EntityTag/Get.php b/civicrm/api/v3/examples/EntityTag/Get.php index a51e13c015f974d6953fe9861b3c6f97246e9548..d3b1392145351614c7051d5409c80683dcf74496 100644 --- a/civicrm/api/v3/examples/EntityTag/Get.php +++ b/civicrm/api/v3/examples/EntityTag/Get.php @@ -7,7 +7,7 @@ */ function entity_tag_get_example() { $params = array( - 'contact_id' => 3, + 'contact_id' => 15, ); try{ @@ -41,10 +41,13 @@ function entity_tag_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 6, + 'id' => 5, 'values' => array( - '6' => array( - 'tag_id' => '6', + '5' => array( + 'id' => '5', + 'entity_table' => 'civicrm_contact', + 'entity_id' => '15', + 'tag_id' => '10', ), ), ); diff --git a/civicrm/api/v3/examples/Event/IsFullOption.php b/civicrm/api/v3/examples/Event/IsFullOption.php index 0eca96b971e40db0a5204481437fd7bc909e4960..556e307c48656940be379eaa24d2daeadc451534 100644 --- a/civicrm/api/v3/examples/Event/IsFullOption.php +++ b/civicrm/api/v3/examples/Event/IsFullOption.php @@ -67,7 +67,7 @@ function event_getsingle_expectedresult() { 'allow_selfcancelxfer' => 0, 'selfcancelxfer_time' => 0, 'is_template' => 0, - 'created_date' => '2017-01-24 08:34:25', + 'created_date' => '2017-02-07 02:22:22', 'is_share' => '1', 'is_confirm_enabled' => '1', 'is_billing_required' => 0, diff --git a/civicrm/api/v3/examples/Group/GetFields.php b/civicrm/api/v3/examples/Group/GetFields.php index 22dfe5250c23be010671e1fe4ea2990769caa02a..0247cb3e9e92f0ad8ba75f5f380fe7070c2f30ec 100644 --- a/civicrm/api/v3/examples/Group/GetFields.php +++ b/civicrm/api/v3/examples/Group/GetFields.php @@ -50,6 +50,9 @@ function group_getfields_expectedresult() { 'title' => 'Group ID', 'description' => 'Group ID', 'required' => TRUE, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'api.aliases' => array( '0' => 'group_id', ), @@ -61,6 +64,9 @@ function group_getfields_expectedresult() { 'description' => 'Internal name of Group.', 'maxlength' => 64, 'size' => 30, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'title' => array( 'name' => 'title', @@ -69,6 +75,9 @@ function group_getfields_expectedresult() { 'description' => 'Name of Group.', 'maxlength' => 64, 'size' => 30, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'api.required' => 1, ), 'description' => array( @@ -78,6 +87,9 @@ function group_getfields_expectedresult() { 'description' => 'Optional verbose description of the group.', 'rows' => 2, 'cols' => 60, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'html' => array( 'type' => 'TextArea', 'rows' => 2, @@ -91,12 +103,18 @@ function group_getfields_expectedresult() { 'description' => 'Module or process which created this group.', 'maxlength' => 64, 'size' => 30, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'saved_search_id' => array( 'name' => 'saved_search_id', 'type' => 1, 'title' => 'Saved Search ID', 'description' => 'FK to saved search table.', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'FKClassName' => 'CRM_Contact_DAO_SavedSearch', 'FKApiName' => 'SavedSearch', ), @@ -105,6 +123,9 @@ function group_getfields_expectedresult() { 'type' => 16, 'title' => 'Group Enabled', 'description' => 'Is this entry active?', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'api.default' => 1, ), 'visibility' => array( @@ -115,6 +136,9 @@ function group_getfields_expectedresult() { 'maxlength' => 24, 'size' => 20, 'default' => 'User and User Admin Only', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'html' => array( 'type' => 'Select', 'maxlength' => 24, @@ -129,18 +153,27 @@ function group_getfields_expectedresult() { 'type' => 32, 'title' => 'Group Where Clause', 'description' => 'the sql where clause if a saved search acl', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'select_tables' => array( 'name' => 'select_tables', 'type' => 32, 'title' => 'Tables For Select Clause', 'description' => 'the tables to be included in a select data', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'where_tables' => array( 'name' => 'where_tables', 'type' => 32, 'title' => 'Tables For Where Clause', 'description' => 'the tables to be included in the count statement', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'group_type' => array( 'name' => 'group_type', @@ -149,6 +182,9 @@ function group_getfields_expectedresult() { 'description' => 'FK to group type', 'maxlength' => 128, 'size' => 45, + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'pseudoconstant' => array( 'optionGroupName' => 'group_type', 'optionEditPath' => 'civicrm/admin/options/group_type', @@ -160,6 +196,9 @@ function group_getfields_expectedresult() { 'title' => 'Group Cache Date', 'description' => 'Date when we created the cache for a smart group', 'required' => '', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'refresh_date' => array( 'name' => 'refresh_date', @@ -167,35 +206,53 @@ function group_getfields_expectedresult() { 'title' => 'Next Group Refresh Time', 'description' => 'Date and time when we need to refresh the cache next.', 'required' => '', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'parents' => array( 'name' => 'parents', 'type' => 32, 'title' => 'Group Parents', 'description' => 'IDs of the parent(s)', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'children' => array( 'name' => 'children', 'type' => 32, 'title' => 'Group Children', 'description' => 'IDs of the child(ren)', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'is_hidden' => array( 'name' => 'is_hidden', 'type' => 16, 'title' => 'Group is Hidden', 'description' => 'Is this group hidden?', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'is_reserved' => array( 'name' => 'is_reserved', 'type' => 16, 'title' => 'Group is Reserved', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', ), 'created_id' => array( 'name' => 'created_id', 'type' => 1, 'title' => 'Group Created By', 'description' => 'FK to contact table.', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'FKApiName' => 'Contact', ), @@ -204,6 +261,9 @@ function group_getfields_expectedresult() { 'type' => 1, 'title' => 'Group Modified By', 'description' => 'FK to contact table.', + 'table_name' => 'civicrm_group', + 'entity' => 'Group', + 'bao' => 'CRM_Contact_BAO_Group', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'FKApiName' => 'Contact', ), diff --git a/civicrm/api/v3/examples/Job/Create.php b/civicrm/api/v3/examples/Job/Create.php index 5c8514e02f5a6128e219c1f9ecc91c859ad995a5..1060d3ccf79f6a0fc7963cb1831ecacb52434be6 100644 --- a/civicrm/api/v3/examples/Job/Create.php +++ b/civicrm/api/v3/examples/Job/Create.php @@ -48,13 +48,14 @@ function job_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 29, + 'id' => 30, 'values' => array( '0' => array( - 'id' => '29', + 'id' => '30', 'domain_id' => '1', 'run_frequency' => 'Daily', 'last_run' => '', + 'scheduled_run_date' => '', 'name' => 'API_Test_Job', 'description' => 'A long description written by hand in cursive', 'api_entity' => 'ApiTestEntity', diff --git a/civicrm/api/v3/examples/Job/Delete.php b/civicrm/api/v3/examples/Job/Delete.php index fe854b3d274c35c704303403f3ba821ae0f18947..40264b4c11e1e4753a067f3b73ce4aff39cc181f 100644 --- a/civicrm/api/v3/examples/Job/Delete.php +++ b/civicrm/api/v3/examples/Job/Delete.php @@ -7,7 +7,7 @@ */ function job_delete_example() { $params = array( - 'id' => 30, + 'id' => 31, ); try{ diff --git a/civicrm/api/v3/examples/Logging/Get.php b/civicrm/api/v3/examples/Logging/Get.php index 2f9a4dae9b6470febb0135cbe08bba472f86a8bb..0e95cdaf508e1322e1fe312ac810423f96f84c9a 100644 --- a/civicrm/api/v3/examples/Logging/Get.php +++ b/civicrm/api/v3/examples/Logging/Get.php @@ -44,52 +44,52 @@ function logging_get_expectedresult() { 'values' => array( '0' => array( 'action' => 'Update', - 'id' => '9', + 'id' => '3', 'field' => 'sort_name', 'from' => 'Anderson, Anthony', 'to' => 'Dwarf, Dopey', 'table' => 'civicrm_contact', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '1' => array( 'action' => 'Update', - 'id' => '9', + 'id' => '3', 'field' => 'display_name', 'from' => 'Mr. Anthony Anderson II', 'to' => 'Mr. Dopey Dwarf II', 'table' => 'civicrm_contact', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '2' => array( 'action' => 'Update', - 'id' => '9', + 'id' => '3', 'field' => 'first_name', 'from' => 'Anthony', 'to' => 'Dopey', 'table' => 'civicrm_contact', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '3' => array( 'action' => 'Update', - 'id' => '9', + 'id' => '3', 'field' => 'last_name', 'from' => 'Anderson', 'to' => 'Dwarf', 'table' => 'civicrm_contact', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '4' => array( 'action' => 'Update', - 'id' => '9', + 'id' => '3', 'field' => 'modified_date', - 'from' => '2016-04-06 02:53:27', - 'to' => '2016-04-06 02:53:44', + 'from' => '2017-02-07 02:36:28', + 'to' => '2017-02-07 02:36:46', 'table' => 'civicrm_contact', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '5' => array( @@ -99,7 +99,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '2', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '6' => array( @@ -107,9 +107,9 @@ function logging_get_expectedresult() { 'id' => '2', 'field' => 'contact_id', 'from' => '', - 'to' => '9', + 'to' => '3', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '7' => array( @@ -119,7 +119,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '8' => array( @@ -129,7 +129,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => 'dopey@mail.com', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '9' => array( @@ -139,7 +139,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => 0, 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '10' => array( @@ -149,7 +149,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => 0, 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '11' => array( @@ -159,7 +159,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => 0, 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '12' => array( @@ -169,7 +169,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => 0, 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '13' => array( @@ -179,7 +179,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '14' => array( @@ -189,7 +189,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '15' => array( @@ -199,7 +199,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), '16' => array( @@ -209,7 +209,7 @@ function logging_get_expectedresult() { 'from' => '', 'to' => '', 'table' => 'civicrm_email', - 'log_date' => '2016-04-06 02:53:44', + 'log_date' => '2017-02-07 02:36:46', 'log_conn_id' => 'wooty wop wop', ), ), diff --git a/civicrm/api/v3/examples/Logging/Revert.php b/civicrm/api/v3/examples/Logging/Revert.php index 1dad9943445b7c93a56ad417bd1b11557af4e4ec..c085b4497c1d80e89821be1a7bb0b99affd91bb8 100644 --- a/civicrm/api/v3/examples/Logging/Revert.php +++ b/civicrm/api/v3/examples/Logging/Revert.php @@ -8,7 +8,7 @@ function logging_revert_example() { $params = array( 'log_conn_id' => 'woot', - 'log_date' => '2016-04-06 02:52:07', + 'log_date' => '2017-02-07 02:35:06', ); try{ diff --git a/civicrm/api/v3/examples/Mailing/Create.php b/civicrm/api/v3/examples/Mailing/Create.php index 0c5410ce6f86a532e6f12dc53112ee19765640c8..b4bcf6f7132ad90d5dc7202159e01a7b8b6638b2 100644 --- a/civicrm/api/v3/examples/Mailing/Create.php +++ b/civicrm/api/v3/examples/Mailing/Create.php @@ -9,18 +9,19 @@ function mailing_create_example() { $params = array( 'subject' => 'Hello {contact.display_name}', 'body_text' => 'This is {contact.display_name}. +https://civicrm.org {domain.address}{action.optOutUrl}', - 'body_html' => '<p>This is {contact.display_name}.</p><p>{domain.address}{action.optOutUrl}</p>', + 'body_html' => '<p>This is {contact.display_name}.</p><p><a href='https://civicrm.org/'>CiviCRM.org</a></p><p>{domain.address}{action.optOutUrl}</p>', 'name' => 'mailing name', - 'created_id' => 9, + 'created_id' => 11, 'header_id' => '', 'footer_id' => '', 'groups' => array( 'include' => array( - '0' => 7, + '0' => 9, ), 'exclude' => array( - '0' => 8, + '0' => 10, ), ), 'mailings' => array( @@ -73,10 +74,10 @@ function mailing_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 4, + 'id' => 5, 'values' => array( - '4' => array( - 'id' => '4', + '5' => array( + 'id' => '5', 'domain_id' => '1', 'header_id' => '', 'footer_id' => '', @@ -93,9 +94,9 @@ function mailing_create_expectedresult() { 'template_options' => '', 'subject' => 'Hello {contact.display_name}', 'body_text' => 'This is {contact.display_name}. -https://civiÅ„crm.org +https://civicrm.org {domain.address}{action.optOutUrl}', - 'body_html' => '<p>This is {contact.display_name}.</p><p><a href=\'https://civiÅ„crm.org/\'>CiviCRM.org</a></p><p>{domain.address}{action.optOutUrl}</p>', + 'body_html' => '<p>This is {contact.display_name}.</p><p><a href=\'https://civicrm.org/\'>CiviCRM.org</a></p><p>{domain.address}{action.optOutUrl}</p>', 'url_tracking' => '1', 'forward_replies' => '', 'auto_responder' => '', @@ -103,7 +104,7 @@ https://civiÅ„crm.org 'is_completed' => '', 'msg_template_id' => '', 'override_verp' => '1', - 'created_id' => '9', + 'created_id' => '11', 'created_date' => '2013-07-28 08:49:19', 'scheduled_id' => '', 'scheduled_date' => '', @@ -119,6 +120,7 @@ https://civiÅ„crm.org 'hash' => '', 'location_type_id' => '', 'email_selection_method' => '', + 'language' => '', 'api.mailing_job.create' => array( 'is_error' => 0, 'version' => 3, @@ -127,7 +129,7 @@ https://civiÅ„crm.org 'values' => array( '0' => array( 'id' => '5', - 'mailing_id' => '4', + 'mailing_id' => '5', 'scheduled_date' => '20130728085413', 'start_date' => '', 'end_date' => '', @@ -148,9 +150,9 @@ https://civiÅ„crm.org 'values' => array( '0' => array( 'id' => '4', - 'mailing_id' => '4', - 'contact_id' => '10', - 'email_id' => '10', + 'mailing_id' => '5', + 'contact_id' => '12', + 'email_id' => '12', 'api.contact.getvalue' => 'Mr. Includer Person II', 'api.email.getvalue' => 'include.me@example.org', ), diff --git a/civicrm/api/v3/examples/Mailing/Delete.php b/civicrm/api/v3/examples/Mailing/Delete.php index d274d8c82503f39b76bdb42f071652fcd678afff..b7f02cbc766fe86f46df736d2e35094a55d3100c 100644 --- a/civicrm/api/v3/examples/Mailing/Delete.php +++ b/civicrm/api/v3/examples/Mailing/Delete.php @@ -7,7 +7,7 @@ */ function mailing_delete_example() { $params = array( - 'id' => 18, + 'id' => 20, ); try{ diff --git a/civicrm/api/v3/examples/Mailing/Submit.php b/civicrm/api/v3/examples/Mailing/Submit.php index 1b328b7e6cc0688af2524f5e37643c3f7c55d15f..ffaae8983dd93e0a0ea4cf2672a862a206b9fdd7 100644 --- a/civicrm/api/v3/examples/Mailing/Submit.php +++ b/civicrm/api/v3/examples/Mailing/Submit.php @@ -9,7 +9,7 @@ function mailing_submit_example() { $params = array( 'scheduled_date' => '2014-12-13 10:00:00', 'approval_date' => '2014-12-13 00:00:00', - 'id' => 16, + 'id' => 18, ); try{ @@ -43,23 +43,27 @@ function mailing_submit_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 16, + 'id' => 18, 'values' => array( - '16' => array( - 'id' => '16', + '18' => array( + 'id' => '18', 'domain_id' => '1', 'header_id' => '', - 'footer_id' => '24', + 'footer_id' => '27', 'reply_id' => '8', 'unsubscribe_id' => '5', 'resubscribe_id' => '6', 'optout_id' => '7', 'name' => 'mailing name', + 'mailing_type' => 'standalone', 'from_name' => 'FIXME', 'from_email' => 'info@EXAMPLE.ORG', 'replyto_email' => 'info@EXAMPLE.ORG', + 'template_type' => 'traditional', + 'template_options' => '', 'subject' => 'Hello {contact.display_name}', 'body_text' => 'This is {contact.display_name}. +https://civicrm.org {domain.address}{action.optOutUrl}', 'body_html' => '<p>Look ma, magic tokens in the markup!</p>', 'url_tracking' => '1', @@ -69,11 +73,11 @@ function mailing_submit_expectedresult() { 'is_completed' => '', 'msg_template_id' => '', 'override_verp' => '1', - 'created_id' => '35', + 'created_id' => '40', 'created_date' => '2013-07-28 08:49:19', - 'scheduled_id' => '36', + 'scheduled_id' => '41', 'scheduled_date' => '20130728085413', - 'approver_id' => '36', + 'approver_id' => '41', 'approval_date' => '20130728085413', 'approval_status_id' => '1', 'approval_note' => '', @@ -83,8 +87,9 @@ function mailing_submit_expectedresult() { 'dedupe_email' => '1', 'sms_provider_id' => '', 'hash' => '67eac7789eaee00', - 'location_type_id' => 0, + 'location_type_id' => '', 'email_selection_method' => 'automatic', + 'language' => '', ), ), ); diff --git a/civicrm/api/v3/examples/MailingAB/Create.php b/civicrm/api/v3/examples/MailingAB/Create.php index e1189215f1a97f26cf2975f6e908676f5fd34bb5..c7ac42c59d77475b87d84c9a2ca9ce0a92536df1 100644 --- a/civicrm/api/v3/examples/MailingAB/Create.php +++ b/civicrm/api/v3/examples/MailingAB/Create.php @@ -57,11 +57,13 @@ function mailing_a_b_create_expectedresult() { 'mailing_id_b' => '2', 'mailing_id_c' => '3', 'domain_id' => '1', - 'testing_criteria_id' => '', - 'winner_criteria_id' => '', + 'testing_criteria' => 'subject', + 'winner_criteria' => 'open', 'specific_url' => '', - 'declare_winning_time' => '20150224231452', + 'declare_winning_time' => '20170209023708', 'group_percentage' => '10', + 'created_id' => '3', + 'created_date' => '2013-07-28 08:49:19', ), ), ); diff --git a/civicrm/api/v3/examples/Membership/Create.php b/civicrm/api/v3/examples/Membership/Create.php index 5f765f3f796f87b73edda0a14af46475ae68bc63..107c3cc7c3ce7d2ffbbac1ff990b0dd3ba5d32dd 100644 --- a/civicrm/api/v3/examples/Membership/Create.php +++ b/civicrm/api/v3/examples/Membership/Create.php @@ -7,14 +7,14 @@ */ function membership_create_example() { $params = array( - 'contact_id' => 76, - 'membership_type_id' => 45, + 'contact_id' => 79, + 'membership_type_id' => 47, 'join_date' => '2006-01-21', 'start_date' => '2006-01-21', 'end_date' => '2006-12-21', 'source' => 'Payment', 'is_override' => 1, - 'status_id' => 29, + 'status_id' => 30, ); try{ @@ -52,13 +52,13 @@ function membership_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '76', - 'membership_type_id' => '45', + 'contact_id' => '79', + 'membership_type_id' => '47', 'join_date' => '20060121000000', 'start_date' => '2013-07-29 00:00:00', 'end_date' => '2013-08-04 00:00:00', 'source' => 'Payment', - 'status_id' => '29', + 'status_id' => '30', 'is_override' => '1', 'owner_membership_id' => '', 'max_related' => '', diff --git a/civicrm/api/v3/examples/Membership/CreateWithCustomData.php b/civicrm/api/v3/examples/Membership/CreateWithCustomData.php index fe9516e6632a3abe5cf44e2516942f2d63cfcf3a..42fa4d5b8b3fc803cde284146c969756da945a46 100644 --- a/civicrm/api/v3/examples/Membership/CreateWithCustomData.php +++ b/civicrm/api/v3/examples/Membership/CreateWithCustomData.php @@ -7,14 +7,14 @@ */ function membership_create_example() { $params = array( - 'contact_id' => 88, - 'membership_type_id' => 53, + 'contact_id' => 91, + 'membership_type_id' => 55, 'join_date' => '2009-01-21', 'start_date' => '2009-01-21', 'end_date' => '2009-12-21', 'source' => 'Payment', 'is_override' => 1, - 'status_id' => 33, + 'status_id' => 34, 'custom_1' => 'custom string', ); @@ -53,13 +53,13 @@ function membership_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '88', - 'membership_type_id' => '53', + 'contact_id' => '91', + 'membership_type_id' => '55', 'join_date' => '20090121000000', 'start_date' => '2013-07-29 00:00:00', 'end_date' => '2013-08-04 00:00:00', 'source' => 'Payment', - 'status_id' => '33', + 'status_id' => '34', 'is_override' => '1', 'owner_membership_id' => '', 'max_related' => '', diff --git a/civicrm/api/v3/examples/Membership/FilterIsCurrent.php b/civicrm/api/v3/examples/Membership/FilterIsCurrent.php index 13dc628132c6f3fbb64e456896bb5338c7fe0bbe..92109b857af7d24e0f6adf31678378234ce5c8ef 100644 --- a/civicrm/api/v3/examples/Membership/FilterIsCurrent.php +++ b/civicrm/api/v3/examples/Membership/FilterIsCurrent.php @@ -9,7 +9,7 @@ */ function membership_get_example() { $params = array( - 'contact_id' => 44, + 'contact_id' => 47, 'filters' => array( 'is_current' => 1, ), @@ -50,13 +50,13 @@ function membership_get_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '44', - 'membership_type_id' => '27', + 'contact_id' => '47', + 'membership_type_id' => '29', 'join_date' => '2009-01-21', 'start_date' => '2013-07-29 00:00:00', 'end_date' => '2013-08-04 00:00:00', 'source' => 'Payment', - 'status_id' => '21', + 'status_id' => '22', 'is_override' => '1', 'is_test' => 0, 'is_pay_later' => 0, diff --git a/civicrm/api/v3/examples/Membership/Get.php b/civicrm/api/v3/examples/Membership/Get.php index 20f24d537d40fe27041bcc23d82640229d588547..8c4fb2aed6cee0b268c69fd7e9da06b0c138e4cf 100644 --- a/civicrm/api/v3/examples/Membership/Get.php +++ b/civicrm/api/v3/examples/Membership/Get.php @@ -7,7 +7,7 @@ */ function membership_get_example() { $params = array( - 'membership_type_id' => 21, + 'membership_type_id' => 23, ); try{ @@ -45,19 +45,19 @@ function membership_get_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '35', - 'membership_type_id' => '21', + 'contact_id' => '38', + 'membership_type_id' => '23', 'join_date' => '2009-01-21', 'start_date' => '2013-07-29 00:00:00', 'end_date' => '2013-08-04 00:00:00', 'source' => 'Payment', - 'status_id' => '18', + 'status_id' => '19', 'is_override' => '1', 'is_test' => 0, 'is_pay_later' => 0, + 'custom_1' => 'custom string', 'membership_name' => 'General', 'relationship_name' => 'Child of', - 'custom_1' => 'custom string', 'custom_1_1' => 'custom string', ), ), diff --git a/civicrm/api/v3/examples/Membership/UpdateCustomData.php b/civicrm/api/v3/examples/Membership/UpdateCustomData.php index 1b593b34c2807d1b835b91db3a497b82cd65aca8..f93f9d1bcdd0c72875b4987ab1e92a4acf2eef32 100644 --- a/civicrm/api/v3/examples/Membership/UpdateCustomData.php +++ b/civicrm/api/v3/examples/Membership/UpdateCustomData.php @@ -7,14 +7,14 @@ */ function membership_create_example() { $params = array( - 'contact_id' => 106, - 'membership_type_id' => 65, + 'contact_id' => 112, + 'membership_type_id' => 69, 'join_date' => '2009-01-21', 'start_date' => '2009-01-21', 'end_date' => '2009-12-21', 'source' => 'Payment', 'is_override' => 1, - 'status_id' => 39, + 'status_id' => 41, 'custom_1' => 'custom string', ); @@ -53,13 +53,13 @@ function membership_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '106', - 'membership_type_id' => '65', + 'contact_id' => '112', + 'membership_type_id' => '69', 'join_date' => '20090121000000', 'start_date' => '2013-07-29 00:00:00', 'end_date' => '2013-08-04 00:00:00', 'source' => 'Payment', - 'status_id' => '39', + 'status_id' => '41', 'is_override' => '1', 'owner_membership_id' => '', 'max_related' => '', diff --git a/civicrm/api/v3/examples/MembershipType/Create.php b/civicrm/api/v3/examples/MembershipType/Create.php index 81cff6e5aeb07bdb70575a1c8396a569b4fa8294..1a01818506bb79707de9e384d1e411ecb580ea93 100644 --- a/civicrm/api/v3/examples/MembershipType/Create.php +++ b/civicrm/api/v3/examples/MembershipType/Create.php @@ -9,7 +9,7 @@ function membership_type_create_example() { $params = array( 'name' => '40+ Membership', 'description' => 'people above 40 are given health instructions', - 'member_of_contact_id' => 13, + 'member_of_contact_id' => 7, 'financial_type_id' => 1, 'domain_id' => '1', 'minimum_fee' => '200', @@ -57,7 +57,7 @@ function membership_type_create_expectedresult() { 'domain_id' => '1', 'name' => '40+ Membership', 'description' => 'people above 40 are given health instructions', - 'member_of_contact_id' => '13', + 'member_of_contact_id' => '7', 'financial_type_id' => '1', 'minimum_fee' => '200', 'duration_unit' => 'month', diff --git a/civicrm/api/v3/examples/MembershipType/Get.php b/civicrm/api/v3/examples/MembershipType/Get.php index f111b04bd406f1dab1d610ada06e05d6965b2db8..e9904be80405085112b41b8f0fdf7a99e93f5d3e 100644 --- a/civicrm/api/v3/examples/MembershipType/Get.php +++ b/civicrm/api/v3/examples/MembershipType/Get.php @@ -48,7 +48,7 @@ function membership_type_get_expectedresult() { 'domain_id' => '1', 'name' => 'General', 'member_of_contact_id' => '4', - 'financial_type_id' => '1', + 'financial_type_id' => '2', 'minimum_fee' => '0.00', 'duration_unit' => 'year', 'duration_interval' => '1', @@ -56,6 +56,7 @@ function membership_type_get_expectedresult() { 'visibility' => 'Public', 'auto_renew' => 0, 'is_active' => '1', + 'contribution_type_id' => '2', ), ), ); diff --git a/civicrm/api/v3/examples/MessageTemplate/Create.php b/civicrm/api/v3/examples/MessageTemplate/Create.php index 094118233901e9664e5cc2f2249446a30327f012..7f2f51393bdd056401db885df59b36fa77e988d7 100644 --- a/civicrm/api/v3/examples/MessageTemplate/Create.php +++ b/civicrm/api/v3/examples/MessageTemplate/Create.php @@ -7,11 +7,11 @@ */ function message_template_create_example() { $params = array( - 'msg_title' => 'msg_title_165', - 'msg_subject' => 'msg_subject_165', - 'msg_text' => 'msg_text_165', - 'msg_html' => 'msg_html_165', - 'workflow_id' => 165, + 'msg_title' => 'msg_title_284', + 'msg_subject' => 'msg_subject_284', + 'msg_text' => 'msg_text_284', + 'msg_html' => 'msg_html_284', + 'workflow_id' => 284, 'is_default' => '1', 'is_reserved' => 1, ); @@ -47,16 +47,16 @@ function message_template_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 67, + 'id' => 69, 'values' => array( - '67' => array( - 'id' => '67', - 'msg_title' => 'msg_title_165', - 'msg_subject' => 'msg_subject_165', - 'msg_text' => 'msg_text_165', - 'msg_html' => 'msg_html_165', + '69' => array( + 'id' => '69', + 'msg_title' => 'msg_title_284', + 'msg_subject' => 'msg_subject_284', + 'msg_text' => 'msg_text_284', + 'msg_html' => 'msg_html_284', 'is_active' => '1', - 'workflow_id' => '165', + 'workflow_id' => '284', 'is_default' => '1', 'is_reserved' => '1', 'is_sms' => '', diff --git a/civicrm/api/v3/examples/MessageTemplate/Delete.php b/civicrm/api/v3/examples/MessageTemplate/Delete.php index 1d47b6f0c8e06a03f58e8cc7ed94c61431d9600a..388e12c2ae0633d642b93fd69bb6f0a97755b991 100644 --- a/civicrm/api/v3/examples/MessageTemplate/Delete.php +++ b/civicrm/api/v3/examples/MessageTemplate/Delete.php @@ -7,7 +7,7 @@ */ function message_template_delete_example() { $params = array( - 'id' => 70, + 'id' => 72, ); try{ diff --git a/civicrm/api/v3/examples/MessageTemplate/Get.php b/civicrm/api/v3/examples/MessageTemplate/Get.php index d3ab1005bcfc1e85262625fbf33ecbc99e8664f6..318d8aada33c7eccc6622c6919dbe2422fd26214 100644 --- a/civicrm/api/v3/examples/MessageTemplate/Get.php +++ b/civicrm/api/v3/examples/MessageTemplate/Get.php @@ -7,11 +7,11 @@ */ function message_template_get_example() { $params = array( - 'msg_title' => 'msg_title_166', - 'msg_subject' => 'msg_subject_166', - 'msg_text' => 'msg_text_166', - 'msg_html' => 'msg_html_166', - 'workflow_id' => 166, + 'msg_title' => 'msg_title_285', + 'msg_subject' => 'msg_subject_285', + 'msg_text' => 'msg_text_285', + 'msg_html' => 'msg_html_285', + 'workflow_id' => 285, 'is_default' => '1', 'is_reserved' => 1, ); @@ -47,20 +47,20 @@ function message_template_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 68, + 'id' => 70, 'values' => array( - '68' => array( - 'id' => '68', - 'msg_title' => 'msg_title_166', - 'msg_subject' => 'msg_subject_166', - 'msg_text' => 'msg_text_166', - 'msg_html' => 'msg_html_166', + '70' => array( + 'id' => '70', + 'msg_title' => 'msg_title_285', + 'msg_subject' => 'msg_subject_285', + 'msg_text' => 'msg_text_285', + 'msg_html' => 'msg_html_285', 'is_active' => '1', - 'workflow_id' => '166', + 'workflow_id' => '285', 'is_default' => '1', 'is_reserved' => '1', 'is_sms' => '1', - 'pdf_format_id' => '166', + 'pdf_format_id' => '285', ), ), ); diff --git a/civicrm/api/v3/examples/OptionGroup/Create.php b/civicrm/api/v3/examples/OptionGroup/Create.php index 7220e3db6ea71a31d785426ce260f916b5feedbc..cee25ba50b24470a8f7671d72e4beca408c4e074 100644 --- a/civicrm/api/v3/examples/OptionGroup/Create.php +++ b/civicrm/api/v3/examples/OptionGroup/Create.php @@ -51,17 +51,18 @@ function option_group_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 93, + 'id' => 92, 'values' => array( '0' => array( - 'id' => '93', + 'id' => '92', 'name' => 'civicrm_event.amount.560', 'title' => '', 'description' => '', + 'data_type' => '', 'is_reserved' => '1', 'is_active' => '1', 'is_locked' => '', - 'api.OptionValue.create' => 784, + 'api.OptionValue.create' => 849, ), ), ); diff --git a/civicrm/api/v3/examples/OptionGroup/Delete.php b/civicrm/api/v3/examples/OptionGroup/Delete.php index cdf194ec7527ee0f8756bc13f8eb29673b4fafa7..20839505b8fad0e44a7de4703ec559312732472c 100644 --- a/civicrm/api/v3/examples/OptionGroup/Delete.php +++ b/civicrm/api/v3/examples/OptionGroup/Delete.php @@ -7,7 +7,7 @@ */ function option_group_delete_example() { $params = array( - 'id' => 98, + 'id' => 97, ); try{ diff --git a/civicrm/api/v3/examples/Order/Cancel.php b/civicrm/api/v3/examples/Order/Cancel.php index 30f5aad2c53ffe79b61dcce9a420ecee6e8d279c..2e6ea262cac1069bc363038a2875641227ceb659 100644 --- a/civicrm/api/v3/examples/Order/Cancel.php +++ b/civicrm/api/v3/examples/Order/Cancel.php @@ -45,7 +45,7 @@ function order_cancel_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '14', + 'contact_id' => '16', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', diff --git a/civicrm/api/v3/examples/Order/Create.php b/civicrm/api/v3/examples/Order/Create.php index 45ea551fcd2a78d96e0535395ff2216895e22ed7..264b1493bd41f5df1f351577c415b93e9481dc3c 100644 --- a/civicrm/api/v3/examples/Order/Create.php +++ b/civicrm/api/v3/examples/Order/Create.php @@ -7,7 +7,7 @@ */ function order_create_example() { $params = array( - 'contact_id' => 7, + 'contact_id' => 8, 'receive_date' => '2010-01-20', 'total_amount' => 200, 'financial_type_id' => 1, @@ -29,7 +29,7 @@ function order_create_example() { ), ), 'params' => array( - 'contact_id' => 7, + 'contact_id' => 8, 'membership_type_id' => 2, 'join_date' => '2006-01-21', 'start_date' => '2006-01-21', @@ -77,7 +77,7 @@ function order_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '7', + 'contact_id' => '8', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', diff --git a/civicrm/api/v3/examples/Order/CreateOrderParticipant.php b/civicrm/api/v3/examples/Order/CreateOrderParticipant.php index aa65ab5fd04560d92027c7d2ad6f677facfbb21e..b1a8a1040119fe0f6099e38192e0cadade97eede 100644 --- a/civicrm/api/v3/examples/Order/CreateOrderParticipant.php +++ b/civicrm/api/v3/examples/Order/CreateOrderParticipant.php @@ -9,7 +9,7 @@ */ function order_create_example() { $params = array( - 'contact_id' => 10, + 'contact_id' => 11, 'receive_date' => '2010-01-20', 'total_amount' => 300, 'financial_type_id' => 1, @@ -41,7 +41,7 @@ function order_create_example() { ), ), 'params' => array( - 'contact_id' => 10, + 'contact_id' => 11, 'event_id' => 1, 'status_id' => 1, 'role_id' => 1, @@ -87,7 +87,7 @@ function order_create_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id' => '10', + 'contact_id' => '11', 'financial_type_id' => '1', 'contribution_page_id' => '', 'payment_instrument_id' => '4', diff --git a/civicrm/api/v3/examples/Order/Get.php b/civicrm/api/v3/examples/Order/Get.php index 10a3c2c84954c4e90795eb29f5e0ef4af09d7443..720596c3d716f9d0b6b6bd3303c80961cf2660e4 100644 --- a/civicrm/api/v3/examples/Order/Get.php +++ b/civicrm/api/v3/examples/Order/Get.php @@ -64,10 +64,11 @@ function order_get_expectedresult() { 'thankyou_date' => '', 'contribution_source' => '', 'amount_level' => '', + 'contribution_recur_id' => '', 'is_test' => 0, 'is_pay_later' => 0, 'contribution_status_id' => '1', - 'check_number' => '', + 'contribution_check_number' => '', 'contribution_campaign_id' => '', 'financial_type_id' => '1', 'financial_type' => 'Donation', @@ -79,7 +80,6 @@ function order_get_expectedresult() { 'fulfilled_date' => '', 'contribution_start_date' => '', 'contribution_end_date' => '', - 'contribution_recur_id' => '', 'financial_account_id' => '1', 'accounting_code' => '4200', 'campaign_id' => '', @@ -90,7 +90,7 @@ function order_get_expectedresult() { 'payment_instrument' => 'Check', 'payment_instrument_id' => '4', 'instrument_id' => '4', - 'contribution_check_number' => '', + 'check_number' => '', 'id' => '1', 'contribution_type_id' => '1', 'line_items' => array( @@ -106,7 +106,8 @@ function order_get_expectedresult() { 'line_total' => '100.00', 'price_field_value_id' => '1', 'financial_type_id' => '1', - 'deductible_amount' => '0.00', + 'non_deductible_amount' => '0.00', + 'contribution_type_id' => '1', ), ), ), diff --git a/civicrm/api/v3/examples/Participant/Create.php b/civicrm/api/v3/examples/Participant/Create.php index 8ab8b98dda950c82bda0a3f0fae1b59e7bb4c044..15aa07367eb16d639b97a40559e9ef68f921b359 100644 --- a/civicrm/api/v3/examples/Participant/Create.php +++ b/civicrm/api/v3/examples/Participant/Create.php @@ -7,8 +7,8 @@ */ function participant_create_example() { $params = array( - 'contact_id' => 4, - 'event_id' => 1, + 'contact_id' => 2, + 'event_id' => 2, 'status_id' => 1, 'role_id' => 1, 'register_date' => '2007-07-21 00:00:00', @@ -51,8 +51,8 @@ function participant_create_expectedresult() { 'values' => array( '4' => array( 'id' => '4', - 'contact_id' => '4', - 'event_id' => '1', + 'contact_id' => '2', + 'event_id' => '2', 'status_id' => '1', 'role_id' => '1', 'register_date' => '20070721000000', diff --git a/civicrm/api/v3/examples/Participant/Get.php b/civicrm/api/v3/examples/Participant/Get.php index 1e06e9540ed7b8de60e0c117102f16cf86b12c17..52ad6116ac95bca0c43be926b76694198468fd10 100644 --- a/civicrm/api/v3/examples/Participant/Get.php +++ b/civicrm/api/v3/examples/Participant/Get.php @@ -49,7 +49,7 @@ function participant_get_expectedresult() { 'contact_sub_type' => '', 'sort_name' => 'Anderson, Anthony', 'display_name' => 'Mr. Anthony Anderson II', - 'event_id' => '5', + 'event_id' => '6', 'event_title' => 'Annual CiviCRM meet', 'event_start_date' => '2013-07-29 00:00:00', 'event_end_date' => '2013-08-04 00:00:00', @@ -60,8 +60,8 @@ function participant_get_expectedresult() { 'event_type' => 'Conference', 'participant_status_id' => '2', 'participant_status' => 'Attended', - 'participant_role' => 'Attendee', 'participant_role_id' => '1', + 'participant_role' => 'Attendee', 'participant_register_date' => '2007-02-19 00:00:00', 'participant_source' => 'Wimbeldon', 'participant_note' => '', diff --git a/civicrm/api/v3/examples/Participant/NestedDelete.php b/civicrm/api/v3/examples/Participant/NestedDelete.php index b9429731c749fa0fe120084bb693aecef60d73b3..37555e4bebf134476d806b95266ca85b6d9bfc20 100644 --- a/civicrm/api/v3/examples/Participant/NestedDelete.php +++ b/civicrm/api/v3/examples/Participant/NestedDelete.php @@ -51,7 +51,7 @@ function participant_get_expectedresult() { 'contact_sub_type' => '', 'sort_name' => 'Anderson, Anthony', 'display_name' => 'Mr. Anthony Anderson II', - 'event_id' => '39', + 'event_id' => '41', 'event_title' => 'Annual CiviCRM meet', 'event_start_date' => '2013-07-29 00:00:00', 'event_end_date' => '2013-08-04 00:00:00', @@ -62,14 +62,14 @@ function participant_get_expectedresult() { 'event_type' => 'Conference', 'participant_status_id' => '2', 'participant_status' => 'Attended', - 'participant_role' => 'Attendee', 'participant_role_id' => '1', + 'participant_role' => 'Attendee', 'participant_register_date' => '2007-02-19 00:00:00', 'participant_source' => 'Wimbeldon', 'participant_note' => '', 'participant_is_pay_later' => 0, 'participant_is_test' => 0, - 'participant_registered_by_id' => '', + 'participant_registered_by_id' => '1', 'participant_discount_name' => '', 'participant_campaign_id' => '', 'id' => '2', @@ -86,7 +86,7 @@ function participant_get_expectedresult() { 'contact_sub_type' => '', 'sort_name' => 'Anderson, Anthony', 'display_name' => 'Mr. Anthony Anderson II', - 'event_id' => '39', + 'event_id' => '41', 'event_title' => 'Annual CiviCRM meet', 'event_start_date' => '2013-07-29 00:00:00', 'event_end_date' => '2013-08-04 00:00:00', @@ -97,8 +97,8 @@ function participant_get_expectedresult() { 'event_type' => 'Conference', 'participant_status_id' => '2', 'participant_status' => 'Attended', - 'participant_role' => 'Attendee', 'participant_role_id' => '1', + 'participant_role' => 'Attendee', 'participant_register_date' => '2007-02-19 00:00:00', 'participant_source' => 'Wimbeldon', 'participant_note' => '', diff --git a/civicrm/api/v3/examples/Participant/NestedEventGet.php b/civicrm/api/v3/examples/Participant/NestedEventGet.php index 78f22366da83a4cf709b7f16674315fef2214902..c6b335e63d25fc8c5d5694b46c74b97506a61373 100644 --- a/civicrm/api/v3/examples/Participant/NestedEventGet.php +++ b/civicrm/api/v3/examples/Participant/NestedEventGet.php @@ -52,7 +52,7 @@ function participant_get_expectedresult() { 'contact_sub_type' => '', 'sort_name' => 'Anderson, Anthony', 'display_name' => 'Mr. Anthony Anderson II', - 'event_id' => '6', + 'event_id' => '7', 'event_title' => 'Annual CiviCRM meet', 'event_start_date' => '2013-07-29 00:00:00', 'event_end_date' => '2013-08-04 00:00:00', @@ -63,8 +63,8 @@ function participant_get_expectedresult() { 'event_type' => 'Conference', 'participant_status_id' => '2', 'participant_status' => 'Attended', - 'participant_role' => 'Attendee', 'participant_role_id' => '1', + 'participant_role' => 'Attendee', 'participant_register_date' => '2007-02-19 00:00:00', 'participant_source' => 'Wimbeldon', 'participant_note' => '', @@ -78,10 +78,10 @@ function participant_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 6, + 'id' => 7, 'values' => array( '0' => array( - 'id' => '6', + 'id' => '7', 'title' => 'Annual CiviCRM meet', 'event_title' => 'Annual CiviCRM meet', 'summary' => 'If you have any CiviCRM related issues or want to track where CiviCRM is heading, Sign up now', diff --git a/civicrm/api/v3/examples/ParticipantStatusType/Create.php b/civicrm/api/v3/examples/ParticipantStatusType/Create.php index 96a4481c51cb8c3ca24a787418518aae2fb4d7eb..9059a8b3225bcc6fb9c6298beaeb74d669ec5f8b 100644 --- a/civicrm/api/v3/examples/ParticipantStatusType/Create.php +++ b/civicrm/api/v3/examples/ParticipantStatusType/Create.php @@ -48,10 +48,10 @@ function participant_status_type_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 17, + 'id' => 18, 'values' => array( - '17' => array( - 'id' => '17', + '18' => array( + 'id' => '18', 'name' => 'test status', 'label' => 'I am a test', 'class' => 'Positive', diff --git a/civicrm/api/v3/examples/ParticipantStatusType/Delete.php b/civicrm/api/v3/examples/ParticipantStatusType/Delete.php index 258aa4af10e59e57fbae27bbf6b09d532a7481a7..ae4fa45657092458eca5bcc4c71fb03d3bca93ef 100644 --- a/civicrm/api/v3/examples/ParticipantStatusType/Delete.php +++ b/civicrm/api/v3/examples/ParticipantStatusType/Delete.php @@ -7,7 +7,7 @@ */ function participant_status_type_delete_example() { $params = array( - 'id' => 18, + 'id' => 19, ); try{ diff --git a/civicrm/api/v3/examples/ParticipantStatusType/Get.php b/civicrm/api/v3/examples/ParticipantStatusType/Get.php index 318d9b5e794231de9768bec671e9dbd1c5b5ee5f..7eb41e6d0f06ef7f713ae90e2e51abcd234b0881 100644 --- a/civicrm/api/v3/examples/ParticipantStatusType/Get.php +++ b/civicrm/api/v3/examples/ParticipantStatusType/Get.php @@ -48,10 +48,10 @@ function participant_status_type_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 17, + 'id' => 18, 'values' => array( - '17' => array( - 'id' => '17', + '18' => array( + 'id' => '18', 'name' => 'test status', 'label' => 'I am a test', 'class' => 'Positive', diff --git a/civicrm/api/v3/examples/Payment/Cancel.php b/civicrm/api/v3/examples/Payment/Cancel.php index bd71ea4426aefbb9642b12ef5aa0d3afdc6bf84e..84e18f440781f0fc9b0e5cc50a610492e5d22423 100644 --- a/civicrm/api/v3/examples/Payment/Cancel.php +++ b/civicrm/api/v3/examples/Payment/Cancel.php @@ -20,7 +20,8 @@ function payment_cancel_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -47,7 +48,7 @@ function payment_cancel_expectedresult() { 'id' => 3, 'from_financial_account_id' => '7', 'to_financial_account_id' => '6', - 'trxn_date' => '20160217204840', + 'trxn_date' => '20170207024650', 'total_amount' => '-150', 'fee_amount' => '0.00', 'net_amount' => '150.00', diff --git a/civicrm/api/v3/examples/Payment/Create.php b/civicrm/api/v3/examples/Payment/Create.php index 4a8efaae330d8ddb6eee4c7492a07fc9b9091dc8..6ece14b33acd50ffc679c8cdd53aafa5d367f884 100644 --- a/civicrm/api/v3/examples/Payment/Create.php +++ b/civicrm/api/v3/examples/Payment/Create.php @@ -20,7 +20,8 @@ function payment_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -47,7 +48,7 @@ function payment_create_expectedresult() { 'id' => '3', 'from_financial_account_id' => '7', 'to_financial_account_id' => '6', - 'trxn_date' => '20160217204833', + 'trxn_date' => '20170207024646', 'total_amount' => '50', 'fee_amount' => '', 'net_amount' => '50', diff --git a/civicrm/api/v3/examples/Payment/CreatePaymentWithLineItems.php b/civicrm/api/v3/examples/Payment/CreatePaymentWithLineItems.php index b9a9b971c183322986d8e8140d681390799c7817..f2b1613a61a4feb76304c0910ade14194cadc631 100644 --- a/civicrm/api/v3/examples/Payment/CreatePaymentWithLineItems.php +++ b/civicrm/api/v3/examples/Payment/CreatePaymentWithLineItems.php @@ -30,7 +30,8 @@ function payment_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -57,7 +58,7 @@ function payment_create_expectedresult() { 'id' => '3', 'from_financial_account_id' => '7', 'to_financial_account_id' => '6', - 'trxn_date' => '20160217204836', + 'trxn_date' => '20170207024648', 'total_amount' => '50', 'fee_amount' => '', 'net_amount' => '50', diff --git a/civicrm/api/v3/examples/Payment/Delete.php b/civicrm/api/v3/examples/Payment/Delete.php index c5be86b58c533827dc58c785417d907ae405136d..51bc8727f919d06702a455d7e6ae2f2c2f164790 100644 --- a/civicrm/api/v3/examples/Payment/Delete.php +++ b/civicrm/api/v3/examples/Payment/Delete.php @@ -20,7 +20,8 @@ function payment_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Payment/Get.php b/civicrm/api/v3/examples/Payment/Get.php index c56d91ec57c4e903ef08e36e2adef37918e97199..ac1263d504c3b8d011b736f7f42336b5bd9fa5e2 100644 --- a/civicrm/api/v3/examples/Payment/Get.php +++ b/civicrm/api/v3/examples/Payment/Get.php @@ -20,7 +20,8 @@ function payment_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Payment/UpdatePayment.php b/civicrm/api/v3/examples/Payment/UpdatePayment.php index d240cbfe2eee316120e9ee92c578710b884b454e..81e017e22305fd9be504ec1ad2c03907fa4c5c27 100644 --- a/civicrm/api/v3/examples/Payment/UpdatePayment.php +++ b/civicrm/api/v3/examples/Payment/UpdatePayment.php @@ -24,7 +24,8 @@ function payment_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -51,7 +52,7 @@ function payment_create_expectedresult() { 'id' => '5', 'from_financial_account_id' => '7', 'to_financial_account_id' => '6', - 'trxn_date' => '20160217204847', + 'trxn_date' => '20170207024653', 'total_amount' => '100', 'fee_amount' => '', 'net_amount' => '100', diff --git a/civicrm/api/v3/examples/PaymentProcessor/Create.php b/civicrm/api/v3/examples/PaymentProcessor/Create.php index 7d911e279af55eaaf77a4baa58610b3edc190579..aa481f9fbcd397362314549aac5ea192cb1b4835 100644 --- a/civicrm/api/v3/examples/PaymentProcessor/Create.php +++ b/civicrm/api/v3/examples/PaymentProcessor/Create.php @@ -52,7 +52,7 @@ function payment_processor_create_expectedresult() { 'domain_id' => '1', 'name' => 'API Test PP', 'description' => '', - 'payment_processor_type_id' => '18', + 'payment_processor_type_id' => '1', 'is_active' => '', 'is_default' => 0, 'is_test' => 0, @@ -68,6 +68,8 @@ function payment_processor_create_expectedresult() { 'billing_mode' => '1', 'is_recur' => 0, 'payment_type' => '1', + 'payment_instrument_id' => '1', + 'accepted_credit_cards' => '', ), ), ); diff --git a/civicrm/api/v3/examples/PaymentProcessor/Delete.php b/civicrm/api/v3/examples/PaymentProcessor/Delete.php index d726926a9a897916e339b398bb90b59929a711b5..a633f4c4bf006f43c06e16eabb55167f6ed84304 100644 --- a/civicrm/api/v3/examples/PaymentProcessor/Delete.php +++ b/civicrm/api/v3/examples/PaymentProcessor/Delete.php @@ -19,7 +19,8 @@ function payment_processor_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function payment_processor_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/PaymentProcessorType/Create.php b/civicrm/api/v3/examples/PaymentProcessorType/Create.php index d7803ec4045fbc39c697a18c0844d4fe24b3f890..d6fc4c1e14323a5e968d814ff5d4953df61fa799 100644 --- a/civicrm/api/v3/examples/PaymentProcessorType/Create.php +++ b/civicrm/api/v3/examples/PaymentProcessorType/Create.php @@ -24,7 +24,8 @@ function payment_processor_type_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -45,10 +46,10 @@ function payment_processor_type_create_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 15, + 'id' => 13, 'values' => array( '0' => array( - 'id' => '15', + 'id' => '13', 'name' => 'API_Test_PP', 'title' => 'API Test Payment Processor', 'description' => '', @@ -70,6 +71,7 @@ function payment_processor_type_create_expectedresult() { 'billing_mode' => '1', 'is_recur' => 0, 'payment_type' => '', + 'payment_instrument_id' => '1', ), ), ); diff --git a/civicrm/api/v3/examples/PaymentProcessorType/Delete.php b/civicrm/api/v3/examples/PaymentProcessorType/Delete.php index 49ac762dd3005e1627744f54fd92013cf2eabc53..d5a6c6d5b088ba18b2d62b670669ad737e61a194 100644 --- a/civicrm/api/v3/examples/PaymentProcessorType/Delete.php +++ b/civicrm/api/v3/examples/PaymentProcessorType/Delete.php @@ -7,7 +7,7 @@ */ function payment_processor_type_delete_example() { $params = array( - 'id' => 17, + 'id' => 15, ); try{ @@ -19,7 +19,8 @@ function payment_processor_type_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PaymentToken/Create.php b/civicrm/api/v3/examples/PaymentToken/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..854c185c462d619c7f28ebc25fff1876999ec06d --- /dev/null +++ b/civicrm/api/v3/examples/PaymentToken/Create.php @@ -0,0 +1,93 @@ +<?php +/** + * Test Generated example demonstrating the PaymentToken.create API. + * + * Create a payment token - Note use of relative dates here: + * @link http://www.php.net/manual/en/datetime.formats.relative.php. + * + * @return array + * API result array + */ +function payment_token_create_example() { + $params = array( + 'token' => 'fancy-token-xxxx', + 'contact_id' => 3, + 'created_id' => 3, + 'payment_processor_id' => 1, + ); + + try{ + $result = civicrm_api3('PaymentToken', 'create', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function payment_token_create_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 1, + 'values' => array( + '1' => array( + 'id' => '1', + 'contact_id' => '3', + 'payment_processor_id' => '1', + 'token' => 'fancy-token-xxxx', + 'created_date' => '2013-07-28 08:49:19', + 'created_id' => '3', + 'expiry_date' => '', + 'email' => '', + 'billing_first_name' => '', + 'billing_middle_name' => '', + 'billing_last_name' => '', + 'masked_account_number' => '', + 'ip_address' => '', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreatePaymentToken" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/PaymentTokenTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/PaymentToken/Delete.php b/civicrm/api/v3/examples/PaymentToken/Delete.php new file mode 100644 index 0000000000000000000000000000000000000000..460d6ad1368d221aca25048c23140fae4d2b7769 --- /dev/null +++ b/civicrm/api/v3/examples/PaymentToken/Delete.php @@ -0,0 +1,70 @@ +<?php +/** + * Test Generated example demonstrating the PaymentToken.delete API. + * + * @return array + * API result array + */ +function payment_token_delete_example() { + $params = array( + 'id' => 3, + ); + + try{ + $result = civicrm_api3('PaymentToken', 'delete', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function payment_token_delete_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'values' => 1, + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testDeletePaymentToken" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/PaymentTokenTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/PaymentToken/Get.php b/civicrm/api/v3/examples/PaymentToken/Get.php new file mode 100644 index 0000000000000000000000000000000000000000..101c847b4080c0c72544ffabd1df6b69f8584c15 --- /dev/null +++ b/civicrm/api/v3/examples/PaymentToken/Get.php @@ -0,0 +1,83 @@ +<?php +/** + * Test Generated example demonstrating the PaymentToken.get API. + * + * @return array + * API result array + */ +function payment_token_get_example() { + $params = array( + 'token' => 'fancy-token-xxxx', + 'contact_id' => 4, + 'created_id' => 4, + 'payment_processor_id' => 2, + ); + + try{ + $result = civicrm_api3('PaymentToken', 'get', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function payment_token_get_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 2, + 'values' => array( + '2' => array( + 'id' => '2', + 'contact_id' => '4', + 'payment_processor_id' => '2', + 'token' => 'fancy-token-xxxx', + 'created_date' => '2013-07-28 08:49:19', + 'created_id' => '4', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testGetPaymentToken" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/PaymentTokenTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/Pcp/Create.php b/civicrm/api/v3/examples/Pcp/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..d3481c70a9236137e56ed99c67f89e6272b87d0a --- /dev/null +++ b/civicrm/api/v3/examples/Pcp/Create.php @@ -0,0 +1,93 @@ +<?php +/** + * Test Generated example demonstrating the Pcp.create API. + * + * @return array + * API result array + */ +function pcp_create_example() { + $params = array( + 'title' => 'Pcp title', + 'contact_id' => 1, + 'page_id' => 1, + 'pcp_block_id' => 1, + ); + + try{ + $result = civicrm_api3('Pcp', 'create', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function pcp_create_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 1, + 'values' => array( + '1' => array( + 'id' => '1', + 'contact_id' => '1', + 'status_id' => 0, + 'title' => 'Pcp title', + 'intro_text' => '', + 'page_text' => '', + 'donate_link_text' => '', + 'page_id' => '1', + 'page_type' => '', + 'pcp_block_id' => '1', + 'is_thermometer' => '', + 'is_honor_roll' => '', + 'goal_amount' => '', + 'currency' => 'USD', + 'is_active' => '', + 'is_notify' => '', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreatePcp" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/PcpTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/Phone/Create.php b/civicrm/api/v3/examples/Phone/Create.php index ea022ea735131d53387be7997a4fab973b8edeba..384cf28e1f37defa64bd7fb4e93b3cf7754441e2 100644 --- a/civicrm/api/v3/examples/Phone/Create.php +++ b/civicrm/api/v3/examples/Phone/Create.php @@ -23,7 +23,8 @@ function phone_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Phone/Delete.php b/civicrm/api/v3/examples/Phone/Delete.php index 363998ab9b7f3efc6a5e9853b880be6f4d7699f9..6f4b97e22a1d4f9a0a9074e018c0c8107cf1f7c7 100644 --- a/civicrm/api/v3/examples/Phone/Delete.php +++ b/civicrm/api/v3/examples/Phone/Delete.php @@ -19,7 +19,8 @@ function phone_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function phone_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/Phone/Get.php b/civicrm/api/v3/examples/Phone/Get.php index f22274d9e26c9a0a7e01d05467b03a4d12345444..ef1a0794c99ec2cf00eab81a3431ff1b55bf0cb7 100644 --- a/civicrm/api/v3/examples/Phone/Get.php +++ b/civicrm/api/v3/examples/Phone/Get.php @@ -20,7 +20,8 @@ function phone_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Pledge/Create.php b/civicrm/api/v3/examples/Pledge/Create.php index 6bd0f386de0fa040e591dd1b447249e97794ae6b..c138d72251f16e01095c8a799c782919ce9c314c 100644 --- a/civicrm/api/v3/examples/Pledge/Create.php +++ b/civicrm/api/v3/examples/Pledge/Create.php @@ -8,9 +8,9 @@ function pledge_create_example() { $params = array( 'contact_id' => 11, - 'pledge_create_date' => '20150222', - 'start_date' => '20150222', - 'scheduled_date' => '20150224', + 'pledge_create_date' => '20170207', + 'start_date' => '20170207', + 'scheduled_date' => '20170209', 'amount' => '100', 'pledge_status_id' => '2', 'pledge_financial_type_id' => '1', @@ -31,7 +31,8 @@ function pledge_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Pledge/Delete.php b/civicrm/api/v3/examples/Pledge/Delete.php index 02b53fdf620f783aec3ed57c8d74af151c7f21ab..17e4780458af390a30fb4581df9818b3236ae4a0 100644 --- a/civicrm/api/v3/examples/Pledge/Delete.php +++ b/civicrm/api/v3/examples/Pledge/Delete.php @@ -19,7 +19,8 @@ function pledge_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Pledge/Get.php b/civicrm/api/v3/examples/Pledge/Get.php index 0ac2a326450f79833a3cb0ebca89bcc257651445..541ca67466de09e863d195f6d3e7474cb21f2e09 100644 --- a/civicrm/api/v3/examples/Pledge/Get.php +++ b/civicrm/api/v3/examples/Pledge/Get.php @@ -19,7 +19,8 @@ function pledge_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,10 +51,11 @@ function pledge_get_expectedresult() { 'display_name' => 'Mr. Anthony Anderson II', 'pledge_id' => '1', 'pledge_amount' => '100.00', - 'pledge_create_date' => '2015-02-22 00:00:00', + 'pledge_create_date' => '2017-02-07 00:00:00', + 'pledge_start_date' => '2017-02-07 00:00:00', 'pledge_status' => 'Pending', 'pledge_total_paid' => '', - 'pledge_next_pay_date' => '2015-02-24 00:00:00', + 'pledge_next_pay_date' => '2017-02-09 00:00:00', 'pledge_next_pay_amount' => '20.00', 'pledge_outstanding_amount' => '', 'pledge_financial_type' => 'Donation', diff --git a/civicrm/api/v3/examples/Pledge/GetFilterHighDate.php b/civicrm/api/v3/examples/Pledge/GetFilterHighDate.php index 6e52589e8e42deded9492fd88a52f2201a8d7453..64b6b3ce57cb3622a6b47d183c8616405e4cdcf9 100644 --- a/civicrm/api/v3/examples/Pledge/GetFilterHighDate.php +++ b/civicrm/api/v3/examples/Pledge/GetFilterHighDate.php @@ -9,7 +9,7 @@ */ function pledge_get_example() { $params = array( - 'pledge_start_date_high' => '20150220231942', + 'pledge_start_date_high' => '20170205024740', ); try{ @@ -21,7 +21,8 @@ function pledge_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -52,10 +53,11 @@ function pledge_get_expectedresult() { 'display_name' => 'Mr. Anthony Anderson II', 'pledge_id' => '2', 'pledge_amount' => '100.00', - 'pledge_create_date' => '2015-02-22 00:00:00', + 'pledge_create_date' => '2017-02-07 00:00:00', + 'pledge_start_date' => '2016-03-04 00:00:00', 'pledge_status' => 'Overdue', 'pledge_total_paid' => '', - 'pledge_next_pay_date' => '2014-03-07 00:00:00', + 'pledge_next_pay_date' => '2016-03-04 00:00:00', 'pledge_next_pay_amount' => '20.00', 'pledge_outstanding_amount' => '20.00', 'pledge_financial_type' => 'Donation', diff --git a/civicrm/api/v3/examples/PledgePayment/Create.php b/civicrm/api/v3/examples/PledgePayment/Create.php index 1e8c21e3eb43c79fe0bf6d18dd8e3c96ac03b3dd..bfbe8f64fae1d27527871097958389d6516da0b8 100644 --- a/civicrm/api/v3/examples/PledgePayment/Create.php +++ b/civicrm/api/v3/examples/PledgePayment/Create.php @@ -23,7 +23,8 @@ function pledge_payment_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PledgePayment/Delete.php b/civicrm/api/v3/examples/PledgePayment/Delete.php index d54893ba45d6583ff0144f8a445fabdf82a0c32d..3a0faa1372ca119e23133559131bd162cc206eca 100644 --- a/civicrm/api/v3/examples/PledgePayment/Delete.php +++ b/civicrm/api/v3/examples/PledgePayment/Delete.php @@ -19,7 +19,8 @@ function pledge_payment_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PledgePayment/Get.php b/civicrm/api/v3/examples/PledgePayment/Get.php index 17f2e27c273eb420003f010764d82a80374ca2e0..20018f0088111dc0855e63abf7832b404da7bea4 100644 --- a/civicrm/api/v3/examples/PledgePayment/Get.php +++ b/civicrm/api/v3/examples/PledgePayment/Get.php @@ -17,7 +17,8 @@ function pledge_payment_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PledgePayment/Update.php b/civicrm/api/v3/examples/PledgePayment/Update.php index eaa3178ceec6a37964d698d00b1628b540bef958..202ba48ac89dbc8270998c51c9d9c97e9dcfdbd2 100644 --- a/civicrm/api/v3/examples/PledgePayment/Update.php +++ b/civicrm/api/v3/examples/PledgePayment/Update.php @@ -20,7 +20,8 @@ function pledge_payment_update_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PriceField/Create.php b/civicrm/api/v3/examples/PriceField/Create.php index 8339479cb382acf2701b24191ebeef8971439f98..054a7a65fb87eebe78a52d768eac2ac6015da35b 100644 --- a/civicrm/api/v3/examples/PriceField/Create.php +++ b/civicrm/api/v3/examples/PriceField/Create.php @@ -24,7 +24,8 @@ function price_field_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PriceField/Delete.php b/civicrm/api/v3/examples/PriceField/Delete.php index 3d23332a4471d8ee0fdbb2fafbda8848ee2c92b2..2e1f037fffde7bb85841ff27105a2a3f127d5049 100644 --- a/civicrm/api/v3/examples/PriceField/Delete.php +++ b/civicrm/api/v3/examples/PriceField/Delete.php @@ -19,7 +19,8 @@ function price_field_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PriceField/Get.php b/civicrm/api/v3/examples/PriceField/Get.php index 953f6d195752075f3eed74defce60d8c0e78a480..c3da7002da476e75372af93c4c339f012efec66c 100644 --- a/civicrm/api/v3/examples/PriceField/Get.php +++ b/civicrm/api/v3/examples/PriceField/Get.php @@ -19,7 +19,8 @@ function price_field_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PriceFieldValue/Create.php b/civicrm/api/v3/examples/PriceFieldValue/Create.php index 567c0b9d06d6f815b5faa1bb228bab6df82c8909..a833aa785e7c5354a7e643947016fa37ced3426e 100644 --- a/civicrm/api/v3/examples/PriceFieldValue/Create.php +++ b/civicrm/api/v3/examples/PriceFieldValue/Create.php @@ -26,7 +26,8 @@ function price_field_value_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -55,6 +56,8 @@ function price_field_value_create_expectedresult() { 'name' => 'memType1', 'label' => 'memType1', 'description' => '', + 'help_pre' => '', + 'help_post' => '', 'amount' => '90', 'count' => '', 'max_value' => '', @@ -64,7 +67,7 @@ function price_field_value_create_expectedresult() { 'is_default' => '', 'is_active' => '1', 'financial_type_id' => '2', - 'deductible_amount' => '', + 'non_deductible_amount' => '', 'contribution_type_id' => '2', ), ), diff --git a/civicrm/api/v3/examples/PriceFieldValue/Delete.php b/civicrm/api/v3/examples/PriceFieldValue/Delete.php index 1eb72a66d3b87470416eb2341d20a4584eb4fb23..084aac721b9d33705fba005d38b7272bb3500fe4 100644 --- a/civicrm/api/v3/examples/PriceFieldValue/Delete.php +++ b/civicrm/api/v3/examples/PriceFieldValue/Delete.php @@ -19,7 +19,8 @@ function price_field_value_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function price_field_value_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/PriceFieldValue/Get.php b/civicrm/api/v3/examples/PriceFieldValue/Get.php index 1944cde832a0ca12509e728bf64dde60a628a0ad..9443533d1c075653b9fd551ad9ab05869f908723 100644 --- a/civicrm/api/v3/examples/PriceFieldValue/Get.php +++ b/civicrm/api/v3/examples/PriceFieldValue/Get.php @@ -19,7 +19,8 @@ function price_field_value_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -52,7 +53,8 @@ function price_field_value_get_expectedresult() { 'is_default' => 0, 'is_active' => '1', 'financial_type_id' => '1', - 'deductible_amount' => '0.00', + 'non_deductible_amount' => '0.00', + 'contribution_type_id' => '1', ), ), ); diff --git a/civicrm/api/v3/examples/PriceSet/Create.php b/civicrm/api/v3/examples/PriceSet/Create.php index 52734d083ed64193fbad3cfbb79d878f78611ffa..bf801c3eac02522d8d03b1a16bcda4e5ebf50264 100644 --- a/civicrm/api/v3/examples/PriceSet/Create.php +++ b/civicrm/api/v3/examples/PriceSet/Create.php @@ -23,7 +23,8 @@ function price_set_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -59,6 +60,7 @@ function price_set_create_expectedresult() { 'financial_type_id' => '', 'is_quick_config' => '', 'is_reserved' => '', + 'min_amount' => '', ), ), ); diff --git a/civicrm/api/v3/examples/PriceSet/Delete.php b/civicrm/api/v3/examples/PriceSet/Delete.php index 5360087383ff66d2ead599b7ea5573966d21d6cc..3929b96906d51f9f119b094d45ca1ccf0f658af8 100644 --- a/civicrm/api/v3/examples/PriceSet/Delete.php +++ b/civicrm/api/v3/examples/PriceSet/Delete.php @@ -19,7 +19,8 @@ function price_set_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/PriceSet/Get.php b/civicrm/api/v3/examples/PriceSet/Get.php index b5468e8277c4500fe50ef7ec387a6152a6af5813..7be052caa0e62fb15a2b904cd49c82608fea3abb 100644 --- a/civicrm/api/v3/examples/PriceSet/Get.php +++ b/civicrm/api/v3/examples/PriceSet/Get.php @@ -19,7 +19,8 @@ function price_set_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,6 +51,7 @@ function price_set_get_expectedresult() { 'extends' => '2', 'is_quick_config' => '1', 'is_reserved' => '1', + 'min_amount' => 0, 'entity' => array(), ), ), diff --git a/civicrm/api/v3/examples/Profile/Apply.php b/civicrm/api/v3/examples/Profile/Apply.php index 60c8da1e7e5c8d34d88a6401c3c631e8a21e359c..57b867c4d3334dd4f238178107e1de1512d08c1d 100644 --- a/civicrm/api/v3/examples/Profile/Apply.php +++ b/civicrm/api/v3/examples/Profile/Apply.php @@ -26,7 +26,8 @@ function profile_apply_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Profile/Get.php b/civicrm/api/v3/examples/Profile/Get.php index 415ba5cde918ec9a56babfdca4099a1042f96599..9a34012a834765680ba3f7c8322eef3a1158837c 100644 --- a/civicrm/api/v3/examples/Profile/Get.php +++ b/civicrm/api/v3/examples/Profile/Get.php @@ -24,7 +24,8 @@ function profile_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Profile/GetFields.php b/civicrm/api/v3/examples/Profile/GetFields.php index 81ec33c5c64501febca9cf5c20950085d8d796d3..48b62cee421c8b890b37e51421dec723af0bcb2c 100644 --- a/civicrm/api/v3/examples/Profile/GetFields.php +++ b/civicrm/api/v3/examples/Profile/GetFields.php @@ -22,7 +22,8 @@ function profile_getfields_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -63,6 +64,8 @@ function profile_getfields_expectedresult() { 'date_format' => '', 'time_format' => '', 'is_required' => 0, + 'table_name' => 'civicrm_value__addcustomfie_1', + 'column_name' => '_addcustomfieldtoprofile_1', 'name' => 'custom_1', 'title' => 'first_name', 'type' => 2, @@ -77,17 +80,25 @@ function profile_getfields_expectedresult() { 'name' => 'postal_code', 'type' => 2, 'title' => 'State Province', - 'maxlength' => 12, - 'size' => 12, + 'description' => 'Store both US (zip5) AND international postal codes. App is responsible for country/region appropriate validation.', + 'maxlength' => 64, + 'size' => 6, 'import' => TRUE, 'where' => 'civicrm_address.postal_code', 'headerPattern' => '/postal|zip/i', 'dataPattern' => '/\\d?\\d{4}(-\\d{4})?/', 'export' => TRUE, + 'table_name' => 'civicrm_address', + 'entity' => 'address', + 'bao' => 'CRM_Core_BAO_Address', + 'html' => array( + 'type' => 'Text', + 'maxlength' => 64, + 'size' => 6, + ), 'api.required' => 0, 'help_pre' => '', 'help_post' => '', - 'entity' => 'address', 'weight' => '2', 'api.aliases' => array(), ), @@ -95,9 +106,15 @@ function profile_getfields_expectedresult() { 'name' => 'state_province_id', 'type' => 1, 'title' => 'State Province', + 'description' => 'Which State_Province does this address belong to.', + 'table_name' => 'civicrm_address', + 'entity' => 'address', + 'bao' => 'CRM_Core_BAO_Address', 'FKClassName' => 'CRM_Core_DAO_StateProvince', 'html' => array( - 'type' => 'Select', + 'type' => 'ChainSelect', + 'size' => 6, + 'maxlength' => 14, ), 'pseudoconstant' => array( 'table' => 'civicrm_state_province', @@ -108,7 +125,6 @@ function profile_getfields_expectedresult() { 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'address', 'weight' => '3', 'api.aliases' => array(), ), @@ -116,9 +132,15 @@ function profile_getfields_expectedresult() { 'name' => 'country_id', 'type' => 1, 'title' => 'Country', + 'description' => 'Which Country does this address belong to.', + 'table_name' => 'civicrm_address', + 'entity' => 'address', + 'bao' => 'CRM_Core_BAO_Address', 'FKClassName' => 'CRM_Core_DAO_Country', 'html' => array( 'type' => 'Select', + 'size' => 6, + 'maxlength' => 14, ), 'pseudoconstant' => array( 'table' => 'civicrm_country', @@ -130,7 +152,6 @@ function profile_getfields_expectedresult() { 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'address', 'weight' => '4', 'api.aliases' => array(), ), @@ -138,6 +159,7 @@ function profile_getfields_expectedresult() { 'name' => 'phone', 'type' => 2, 'title' => 'Phone', + 'description' => 'Complete phone number.', 'maxlength' => 32, 'size' => 20, 'import' => TRUE, @@ -145,10 +167,17 @@ function profile_getfields_expectedresult() { 'headerPattern' => '/phone/i', 'dataPattern' => '/^[\\d\\(\\)\\-\\.\\s]+$/', 'export' => TRUE, + 'table_name' => 'civicrm_phone', + 'entity' => 'phone', + 'bao' => 'CRM_Core_BAO_Phone', + 'html' => array( + 'type' => 'Text', + 'maxlength' => 32, + 'size' => 20, + ), 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'phone', 'weight' => '5', 'api.aliases' => array(), ), @@ -156,21 +185,26 @@ function profile_getfields_expectedresult() { 'name' => 'email', 'type' => 2, 'title' => 'Email', + 'description' => 'Email address', 'maxlength' => 254, - 'size' => 20, + 'size' => 30, 'import' => TRUE, 'where' => 'civicrm_email.email', 'headerPattern' => '/e.?mail/i', 'dataPattern' => '/^[a-zA-Z][\\w\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$/', 'export' => TRUE, 'rule' => 'email', + 'table_name' => 'civicrm_email', + 'entity' => 'email', + 'bao' => 'CRM_Core_BAO_Email', 'html' => array( 'type' => 'Text', + 'maxlength' => 254, + 'size' => 30, ), 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'email', 'weight' => '6', 'api.aliases' => array( '0' => 'email-Primary', @@ -180,6 +214,7 @@ function profile_getfields_expectedresult() { 'name' => 'last_name', 'type' => 2, 'title' => 'Last Name', + 'description' => 'Last Name.', 'maxlength' => 64, 'size' => 30, 'import' => TRUE, @@ -187,13 +222,17 @@ function profile_getfields_expectedresult() { 'headerPattern' => '/^last|(l(ast\\s)?name)$/i', 'dataPattern' => '/^\\w+(\\s\\w+)?+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', + 'maxlength' => 64, + 'size' => 30, ), 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'contact', 'weight' => '7', 'api.aliases' => array(), ), @@ -201,6 +240,7 @@ function profile_getfields_expectedresult() { 'name' => 'first_name', 'type' => 2, 'title' => 'First Name', + 'description' => 'First Name.', 'maxlength' => 64, 'size' => 30, 'import' => TRUE, @@ -208,13 +248,17 @@ function profile_getfields_expectedresult() { 'headerPattern' => '/^first|(f(irst\\s)?name)$/i', 'dataPattern' => '/^\\w+$/', 'export' => TRUE, + 'table_name' => 'civicrm_contact', + 'entity' => 'contact', + 'bao' => 'CRM_Contact_BAO_Contact', 'html' => array( 'type' => 'Text', + 'maxlength' => 64, + 'size' => 30, ), 'api.required' => '1', 'help_pre' => '', 'help_post' => '', - 'entity' => 'contact', 'weight' => '8', 'api.aliases' => array(), ), diff --git a/civicrm/api/v3/examples/Profile/Submit.php b/civicrm/api/v3/examples/Profile/Submit.php index 03c6ef75d730991d92f831a32ed1d26e3b0c3052..a8b26e325c92ab743a0c4e343a55c140edb2d7ad 100644 --- a/civicrm/api/v3/examples/Profile/Submit.php +++ b/civicrm/api/v3/examples/Profile/Submit.php @@ -26,7 +26,8 @@ function profile_submit_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Relationship/BetweenRelationshipType.php b/civicrm/api/v3/examples/Relationship/BetweenRelationshipType.php index 2a04935a837e26e50e985805d54efe21507f6d3f..d7dfa39ddd96d86b634df63f2c4e75b87370170a 100644 --- a/civicrm/api/v3/examples/Relationship/BetweenRelationshipType.php +++ b/civicrm/api/v3/examples/Relationship/BetweenRelationshipType.php @@ -11,8 +11,8 @@ function relationship_get_example() { $params = array( 'relationship_type_id' => array( 'BETWEEN' => array( - '0' => 33, - '1' => 35, + '0' => 36, + '1' => 38, ), ), ); @@ -26,7 +26,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,34 +51,31 @@ function relationship_get_expectedresult() { 'values' => array( '2' => array( 'id' => '2', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '33', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '36', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), '3' => array( 'id' => '3', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '34', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '37', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), '4' => array( 'id' => '4', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '35', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '38', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), diff --git a/civicrm/api/v3/examples/Relationship/Create.php b/civicrm/api/v3/examples/Relationship/Create.php index 1c4c1586f189e044104d5a22bcce162412284620..1978de2bde515f2de131aac8e25aa3c7fb295c42 100644 --- a/civicrm/api/v3/examples/Relationship/Create.php +++ b/civicrm/api/v3/examples/Relationship/Create.php @@ -25,7 +25,8 @@ function relationship_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Relationship/Delete.php b/civicrm/api/v3/examples/Relationship/Delete.php index 1e8cafd512ec553a51106e49fbd556a95f3c25e6..74e4ffc30211eb479fa5d9553adff115f2ed3ec3 100644 --- a/civicrm/api/v3/examples/Relationship/Delete.php +++ b/civicrm/api/v3/examples/Relationship/Delete.php @@ -19,7 +19,8 @@ function relationship_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Relationship/Get.php b/civicrm/api/v3/examples/Relationship/Get.php index b1a865ccb105b5e123f2811629446e64f8d66427..9d21e1f7812408479a8596e3c0eaa6183199a110 100644 --- a/civicrm/api/v3/examples/Relationship/Get.php +++ b/civicrm/api/v3/examples/Relationship/Get.php @@ -19,7 +19,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -49,7 +50,6 @@ function relationship_get_expectedresult() { 'relationship_type_id' => '22', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, 'custom_1' => 'custom string', diff --git a/civicrm/api/v3/examples/Relationship/INRelationshipType.php b/civicrm/api/v3/examples/Relationship/INRelationshipType.php index afbd42c46594946d19139819316f590e16b26a6e..3a907c0f1a27ba4575a28d3ca72e563f28cfd5de 100644 --- a/civicrm/api/v3/examples/Relationship/INRelationshipType.php +++ b/civicrm/api/v3/examples/Relationship/INRelationshipType.php @@ -11,8 +11,8 @@ function relationship_get_example() { $params = array( 'relationship_type_id' => array( 'IN' => array( - '0' => 33, - '1' => 34, + '0' => 36, + '1' => 37, ), ), ); @@ -26,7 +26,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,23 +51,21 @@ function relationship_get_expectedresult() { 'values' => array( '2' => array( 'id' => '2', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '33', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '36', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), '3' => array( 'id' => '3', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '34', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '37', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), diff --git a/civicrm/api/v3/examples/Relationship/NotBetweenRelationshipType.php b/civicrm/api/v3/examples/Relationship/NotBetweenRelationshipType.php index 091ea47cec2bedfc8d8cd4bf47e0fcaee3df4f6d..31a8a7345443d2c6d1e77244897b1e26874b2871 100644 --- a/civicrm/api/v3/examples/Relationship/NotBetweenRelationshipType.php +++ b/civicrm/api/v3/examples/Relationship/NotBetweenRelationshipType.php @@ -11,8 +11,8 @@ function relationship_get_example() { $params = array( 'relationship_type_id' => array( 'NOT BETWEEN' => array( - '0' => 33, - '1' => 35, + '0' => 36, + '1' => 38, ), ), ); @@ -26,7 +26,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -51,12 +52,11 @@ function relationship_get_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '32', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '35', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), diff --git a/civicrm/api/v3/examples/Relationship/NotInRelationshipType.php b/civicrm/api/v3/examples/Relationship/NotInRelationshipType.php index 024c3952e869162d00e4f06690d9aac1d359dc88..5e77fe8b30c0f6d7629aa45bf261f611aaa545f1 100644 --- a/civicrm/api/v3/examples/Relationship/NotInRelationshipType.php +++ b/civicrm/api/v3/examples/Relationship/NotInRelationshipType.php @@ -11,8 +11,8 @@ function relationship_get_example() { $params = array( 'relationship_type_id' => array( 'NOT IN' => array( - '0' => 33, - '1' => 34, + '0' => 36, + '1' => 37, ), ), ); @@ -26,7 +26,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,23 +51,21 @@ function relationship_get_expectedresult() { 'values' => array( '1' => array( 'id' => '1', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '32', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '35', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), '4' => array( 'id' => '4', - 'contact_id_a' => '87', - 'contact_id_b' => '89', - 'relationship_type_id' => '35', + 'contact_id_a' => '99', + 'contact_id_b' => '101', + 'relationship_type_id' => '38', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), diff --git a/civicrm/api/v3/examples/Relationship/filterIsCurrent.php b/civicrm/api/v3/examples/Relationship/filterIsCurrent.php index d12bccc3f97204dc54295f0db79234e7099510a5..c4aee7a37ae389b2a81181e3745ba9a70d6324f9 100644 --- a/civicrm/api/v3/examples/Relationship/filterIsCurrent.php +++ b/civicrm/api/v3/examples/Relationship/filterIsCurrent.php @@ -23,7 +23,8 @@ function relationship_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -48,12 +49,11 @@ function relationship_get_expectedresult() { 'values' => array( '2' => array( 'id' => '2', - 'contact_id_a' => '83', - 'contact_id_b' => '85', - 'relationship_type_id' => '31', + 'contact_id_a' => '95', + 'contact_id_b' => '97', + 'relationship_type_id' => '34', 'start_date' => '2013-07-29 00:00:00', 'is_active' => '1', - 'description' => '', 'is_permission_a_b' => 0, 'is_permission_b_a' => 0, ), diff --git a/civicrm/api/v3/examples/RelationshipType/Create.php b/civicrm/api/v3/examples/RelationshipType/Create.php index 2d458c4dbf02e1cb1c41051399e614a8c704266d..42826f114c59de16ff01686fe3dfdd8fdc774470 100644 --- a/civicrm/api/v3/examples/RelationshipType/Create.php +++ b/civicrm/api/v3/examples/RelationshipType/Create.php @@ -25,7 +25,8 @@ function relationship_type_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/RelationshipType/Delete.php b/civicrm/api/v3/examples/RelationshipType/Delete.php index 6b1dd50373021ab1bcdcee64d14db5a7a3557ed6..d331378cdc9f95633737dad61686ff581a444e37 100644 --- a/civicrm/api/v3/examples/RelationshipType/Delete.php +++ b/civicrm/api/v3/examples/RelationshipType/Delete.php @@ -19,7 +19,8 @@ function relationship_type_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function relationship_type_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/ReportTemplate/Getrows.php b/civicrm/api/v3/examples/ReportTemplate/Getrows.php index 8c790439fd8ade252affc0773d26f05b1687cd0d..25dc1d5fc6b40a18c9ad89e0dd0581833e09fb97 100644 --- a/civicrm/api/v3/examples/ReportTemplate/Getrows.php +++ b/civicrm/api/v3/examples/ReportTemplate/Getrows.php @@ -27,7 +27,8 @@ function report_template_getrows_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -50,16 +51,16 @@ function report_template_getrows_expectedresult() { 'count' => 2, 'values' => array( '0' => array( - 'civicrm_contact_sort_name' => 'Default Organization', - 'civicrm_contact_id' => '1', - 'civicrm_contact_sort_name_link' => '/index.php?q=civicrm/report/contact/detail&reset=1&force=1&id_op=eq&id_value=1', - 'civicrm_contact_sort_name_hover' => 'View Constituent Detail Report for this contact.', - ), - '1' => array( 'civicrm_contact_sort_name' => 'Second Domain', 'civicrm_contact_id' => '2', 'civicrm_contact_sort_name_link' => '/index.php?q=civicrm/report/contact/detail&reset=1&force=1&id_op=eq&id_value=2', - 'civicrm_contact_sort_name_hover' => 'View Constituent Detail Report for this contact.', + 'civicrm_contact_sort_name_hover' => 'View Contact Detail Report for this contact', + ), + '1' => array( + 'civicrm_contact_sort_name' => 'Unit Test Organization', + 'civicrm_contact_id' => '1', + 'civicrm_contact_sort_name_link' => '/index.php?q=civicrm/report/contact/detail&reset=1&force=1&id_op=eq&id_value=1', + 'civicrm_contact_sort_name_hover' => 'View Contact Detail Report for this contact', ), ), 'metadata' => array( diff --git a/civicrm/api/v3/examples/ReportTemplate/Getstatistics.php b/civicrm/api/v3/examples/ReportTemplate/Getstatistics.php index bc98a485fe3b9c526b77a2faee029a6085eeff8a..d9c9dc340c8941dfd0dc4075e7aec36069967153 100644 --- a/civicrm/api/v3/examples/ReportTemplate/Getstatistics.php +++ b/civicrm/api/v3/examples/ReportTemplate/Getstatistics.php @@ -9,7 +9,7 @@ */ function report_template_getstatistics_example() { $params = array( - 'report_id' => 'contribute/recursummary', + 'report_id' => 'contribute/deferredrevenue', ); try{ @@ -21,7 +21,8 @@ function report_template_getstatistics_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -41,16 +42,8 @@ function report_template_getstatistics_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 1, - 'id' => 'counts', - 'values' => array( - 'counts' => array( - 'rowCount' => array( - 'title' => 'Row(s) Listed', - 'value' => 0, - ), - ), - ), + 'count' => 0, + 'values' => '', ); return $expectedResult; diff --git a/civicrm/api/v3/examples/SavedSearch/Create.php b/civicrm/api/v3/examples/SavedSearch/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..31d677d93a26ce2cc8bfce0308b5bea55afe0a47 --- /dev/null +++ b/civicrm/api/v3/examples/SavedSearch/Create.php @@ -0,0 +1,127 @@ +<?php +/** + * Test Generated example demonstrating the SavedSearch.create API. + * + * @return array + * API result array + */ +function saved_search_create_example() { + $params = array( + 'form_values' => array( + 'relation_type_id' => '6_a_b', + 'relation_target_name' => 'Default Organization', + ), + 'api.Group.create' => array( + 'name' => 'my_smartgroup', + 'title' => 'my smartgroup', + 'description' => 'Volunteers for the default organization', + 'saved_search_id' => '$value.id', + 'is_active' => 1, + 'visibility' => 'User and User Admin Only', + 'is_hidden' => 0, + 'is_reserved' => 0, + ), + ); + + try{ + $result = civicrm_api3('SavedSearch', 'create', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function saved_search_create_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 3, + 'values' => array( + '3' => array( + 'id' => '3', + 'form_values' => array( + 'relation_type_id' => '6_a_b', + 'relation_target_name' => 'Default Organization', + ), + 'mapping_id' => '', + 'search_custom_id' => '', + 'where_clause' => '', + 'select_tables' => '', + 'where_tables' => '', + 'api.Group.create' => array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 1, + 'values' => array( + '0' => array( + 'id' => '1', + 'name' => 'my_smartgroup', + 'title' => 'my smartgroup', + 'description' => 'Volunteers for the default organization', + 'source' => '', + 'saved_search_id' => '3', + 'is_active' => '1', + 'visibility' => 'User and User Admin Only', + 'where_clause' => ' ( ( `civicrm_group_contact_cache_1`.group_id IN (\"1\") ) ) ', + 'select_tables' => 'a:8:{s:15:\"civicrm_contact\";i:1;s:15:\"civicrm_address\";i:1;s:15:\"civicrm_country\";i:1;s:13:\"civicrm_email\";i:1;s:13:\"civicrm_phone\";i:1;s:10:\"civicrm_im\";i:1;s:19:\"civicrm_worldregion\";i:1;s:31:\"`civicrm_group_contact_cache_1`\";s:132:\" LEFT JOIN civicrm_group_contact_cache `civicrm_group_contact_cache_1` ON contact_a.id = `civicrm_group_contact_cache_1`.contact_id \";}', + 'where_tables' => 'a:2:{s:15:\"civicrm_contact\";i:1;s:31:\"`civicrm_group_contact_cache_1`\";s:132:\" LEFT JOIN civicrm_group_contact_cache `civicrm_group_contact_cache_1` ON contact_a.id = `civicrm_group_contact_cache_1`.contact_id \";}', + 'group_type' => '', + 'cache_date' => '', + 'refresh_date' => '', + 'parents' => '', + 'children' => '', + 'is_hidden' => 0, + 'is_reserved' => 0, + 'created_id' => '', + 'modified_id' => '', + ), + ), + ), + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreateSavedSearchWithSmartGroup" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/SavedSearchTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/SavedSearch/Delete.php b/civicrm/api/v3/examples/SavedSearch/Delete.php new file mode 100644 index 0000000000000000000000000000000000000000..3d0052b6b9a83944cd339366144943dc509848d8 --- /dev/null +++ b/civicrm/api/v3/examples/SavedSearch/Delete.php @@ -0,0 +1,70 @@ +<?php +/** + * Test Generated example demonstrating the SavedSearch.delete API. + * + * @return array + * API result array + */ +function saved_search_delete_example() { + $params = array( + 'id' => 4, + ); + + try{ + $result = civicrm_api3('SavedSearch', 'delete', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function saved_search_delete_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'values' => 1, + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testDeleteSavedSearch" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/SavedSearchTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/SavedSearch/Get.php b/civicrm/api/v3/examples/SavedSearch/Get.php new file mode 100644 index 0000000000000000000000000000000000000000..14adb3a11b2a04907b73efbe63e67a19430a6000 --- /dev/null +++ b/civicrm/api/v3/examples/SavedSearch/Get.php @@ -0,0 +1,79 @@ +<?php +/** + * Test Generated example demonstrating the SavedSearch.get API. + * + * @return array + * API result array + */ +function saved_search_get_example() { + $params = array( + 'id' => 2, + ); + + try{ + $result = civicrm_api3('SavedSearch', 'get', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function saved_search_get_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 2, + 'values' => array( + '2' => array( + 'id' => '2', + 'form_values' => array( + 'relation_type_id' => '6_a_b', + 'relation_target_name' => 'Default Organization', + ), + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreateAndGetSavedSearch" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/SavedSearchTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/Setting/Create.php b/civicrm/api/v3/examples/Setting/Create.php index 466890049cfd068a2b8245e18d50d3fac2571339..3f92f961375dac70c2befd52751274a93682f82b 100644 --- a/civicrm/api/v3/examples/Setting/Create.php +++ b/civicrm/api/v3/examples/Setting/Create.php @@ -20,7 +20,8 @@ function setting_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/CreateAllDomains.php b/civicrm/api/v3/examples/Setting/CreateAllDomains.php index ec2115963355a78e42cc667429417a3ae23d63c0..37a4d5efc4b86e3a81666bcc3a935a3b7800d80f 100644 --- a/civicrm/api/v3/examples/Setting/CreateAllDomains.php +++ b/civicrm/api/v3/examples/Setting/CreateAllDomains.php @@ -22,7 +22,8 @@ function setting_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/CreateSettingCurrentDomain.php b/civicrm/api/v3/examples/Setting/CreateSettingCurrentDomain.php index a43b968efca8e906075ad68f3aae67b5198c306b..c0e189dcb2fa1c02e4459b203a22292892b72762 100644 --- a/civicrm/api/v3/examples/Setting/CreateSettingCurrentDomain.php +++ b/civicrm/api/v3/examples/Setting/CreateSettingCurrentDomain.php @@ -21,7 +21,8 @@ function setting_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/CreateSpecifiedDomains.php b/civicrm/api/v3/examples/Setting/CreateSpecifiedDomains.php index e889f6c3a070346c726bfbd92d044b7737ca0986..a54f24ab94976f8d2debb7adba08be2454b1328e 100644 --- a/civicrm/api/v3/examples/Setting/CreateSpecifiedDomains.php +++ b/civicrm/api/v3/examples/Setting/CreateSpecifiedDomains.php @@ -25,7 +25,8 @@ function setting_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/Get.php b/civicrm/api/v3/examples/Setting/Get.php index 270c1e5e5484132d0a8da230a5b11cf2db02d2b9..522fb14a8e2b157d8bc3a9236b32d3f9f4fed311 100644 --- a/civicrm/api/v3/examples/Setting/Get.php +++ b/civicrm/api/v3/examples/Setting/Get.php @@ -20,7 +20,8 @@ function setting_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/GetAllDomains.php b/civicrm/api/v3/examples/Setting/GetAllDomains.php index 4aab2582fa19878c626e700763cb1a0ecfbf0fd5..3a446f13d893419432be26df0852df762b3c234e 100644 --- a/civicrm/api/v3/examples/Setting/GetAllDomains.php +++ b/civicrm/api/v3/examples/Setting/GetAllDomains.php @@ -22,7 +22,8 @@ function setting_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/GetDefaults.php b/civicrm/api/v3/examples/Setting/GetDefaults.php index 3cb02ca81398b28ecf634bf5fbcb28b80989145f..1a5e7d9b2d8f4298b62550b1c9a3c6c9692605ea 100644 --- a/civicrm/api/v3/examples/Setting/GetDefaults.php +++ b/civicrm/api/v3/examples/Setting/GetDefaults.php @@ -21,7 +21,8 @@ function setting_getdefaults_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/GetFields.php b/civicrm/api/v3/examples/Setting/GetFields.php index df623eb6ceccbce7196ca877577623651e759c72..9e6170e70d97560be91a4567b6e038b3394b852b 100644 --- a/civicrm/api/v3/examples/Setting/GetFields.php +++ b/civicrm/api/v3/examples/Setting/GetFields.php @@ -19,7 +19,8 @@ function setting_getfields_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -39,7 +40,7 @@ function setting_getfields_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 91, + 'count' => 151, 'values' => array( 'address_standardization_provider' => array( 'group_name' => 'Address Preferences', @@ -84,6 +85,20 @@ function setting_getfields_expectedresult() { 'help_text' => 'Web Service URL', 'validate_callback' => 'CRM_Utils_Rule::url', ), + 'hideCountryMailingLabels' => array( + 'group_name' => 'Address Preferences', + 'group' => 'address', + 'name' => 'hideCountryMailingLabels', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Hide Country in Mailing Labels when same as domain country', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Do not display the country field in mailing labels when the country is the same as that of the domain', + 'help_text' => '', + ), 'tag_unconfirmed' => array( 'group_name' => 'Campaign Preferences', 'group' => 'campaign', @@ -126,6 +141,135 @@ function setting_getfields_expectedresult() { 'description' => 'Is the CVV code required for back office credit card transactions', 'help_text' => 'If set it back-office credit card transactions will required a cvv code. Leave as required unless you have a very strong reason to change', ), + 'contribution_invoice_settings' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'contribution_invoice_settings', + 'type' => 'Array', + 'default' => array( + 'invoice_prefix' => 'INV_', + 'credit_notes_prefix' => 'CN_', + 'due_date' => '10', + 'due_date_period' => 'days', + 'notes' => '', + 'tax_term' => 'Sales Tax', + 'tax_display_settings' => 'Inclusive', + ), + 'add' => '4.7', + 'title' => 'Contribution Invoice Settings', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'invoicing' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'invoicing', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'quick_form_type' => 'Element', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Enable Tax and Invoicing', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'acl_financial_type' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'acl_financial_type', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'quick_form_type' => 'Element', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Enable Access Control by Financial Type', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'deferred_revenue_enabled' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'deferred_revenue_enabled', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'quick_form_type' => 'Element', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Enable Deferred Revenue', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'default_invoice_page' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'default_invoice_page', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'default' => '', + 'pseudoconstant' => array( + 'name' => 'contributionPage', + ), + 'html_type' => 'select', + 'add' => '4.7', + 'title' => 'Default invoice payment page', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'financial_account_bal_enable' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'financial_account_bal_enable', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'quick_form_type' => 'Element', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Enable Financial Account Balances', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'prior_financial_period' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'prior_financial_period', + 'type' => 'activityDate', + 'quick_form_type' => 'Date', + 'html_type' => 'Date', + 'default' => '', + 'add' => '4.7', + 'title' => 'Prior Financial Period', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'always_post_to_accounts_receivable' => array( + 'group_name' => 'Contribute Preferences', + 'group' => 'contribute', + 'name' => 'always_post_to_accounts_receivable', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'quick_form_type' => 'Element', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Always post to Accounts Receivable?', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), 'contact_view_options' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', @@ -135,20 +279,7 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'optionGroupName' => 'contact_view_options', ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '6', - '6' => '7', - '7' => '8', - '8' => '9', - '9' => '10', - '10' => '11', - '11' => '13', - ), + 'default' => '123456789101113', 'add' => '4.1', 'title' => 'Viewing Contacts', 'is_domain' => '1', @@ -165,19 +296,7 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'optionGroupName' => 'contact_edit_options', ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '6', - '6' => '7', - '7' => '8', - '8' => '9', - '9' => '10', - '10' => '11', - ), + 'default' => '123456789111214151617', 'add' => '4.1', 'title' => 'Editing Contacts', 'is_domain' => 1, @@ -193,25 +312,7 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'optionGroupName' => 'advanced_search_options', ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '6', - '6' => '7', - '7' => '8', - '8' => '9', - '9' => '10', - '10' => '12', - '11' => '13', - '12' => '15', - '13' => '16', - '14' => '17', - '15' => '18', - '16' => '19', - ), + 'default' => '123456789101112131516171819', 'add' => '4.1', 'title' => 'Contact Search', 'is_domain' => 1, @@ -228,16 +329,7 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'optionGroupName' => 'user_dashboard_options', ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '7', - '6' => '8', - '7' => '9', - ), + 'default' => '1234578', 'add' => '4.1', 'title' => 'Contact Dashboard', 'is_domain' => 1, @@ -254,16 +346,7 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'optionGroupName' => 'address_options', ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '4', - '3' => '5', - '4' => '8', - '5' => '9', - '6' => '10', - '7' => '11', - ), + 'default' => '123456891011', 'add' => '4.1', 'title' => 'Addressing Options', 'is_domain' => 1, @@ -337,13 +420,28 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), + 'remote_profile_submissions' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'remote_profile_submissions', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => '', + 'html_type' => 'radio', + 'add' => '4.7', + 'title' => 'Accept profile submissions from external sites', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, CiviCRM will permit submissions from external sites to profiles. This is disabled by default to limit abuse.', + 'help_text' => '', + ), 'editor_id' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'editor_id', 'type' => 'String', - 'html_type' => 'Text', - 'default' => '', + 'html_type' => 'Select', + 'default' => 'CKEditor', 'add' => '4.1', 'title' => 'Wysiwig Editor', 'is_domain' => 1, @@ -357,7 +455,7 @@ function setting_getfields_expectedresult() { 'name' => 'contact_ajax_check_similar', 'type' => 'String', 'html_type' => 'Text', - 'default' => '', + 'default' => '1', 'add' => '4.1', 'title' => 'Ajax Check Similar', 'is_domain' => 1, @@ -385,7 +483,7 @@ function setting_getfields_expectedresult() { 'name' => 'activity_assignee_notification', 'type' => 'String', 'html_type' => 'Text', - 'default' => '', + 'default' => '1', 'add' => '4.1', 'title' => 'Notify Activity Assignees', 'is_domain' => 1, @@ -399,7 +497,7 @@ function setting_getfields_expectedresult() { 'name' => 'activity_assignee_notification_ics', 'type' => 'String', 'html_type' => 'Text', - 'default' => '', + 'default' => 0, 'add' => '4.3', 'title' => 'Include ICal Invite to Activity Assignees', 'is_domain' => 1, @@ -412,24 +510,16 @@ function setting_getfields_expectedresult() { 'group' => 'core', 'name' => 'contact_autocomplete_options', 'type' => 'String', - 'html_type' => 'checkboxes', + 'quick_form_type' => 'CheckBox', 'pseudoconstant' => array( - 'optionGroupName' => 'contact_autocomplete_options', - ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '6', - '6' => '7', + 'callback' => 'CRM_Admin_Form_Setting_Search::getContactAutocompleteOptions', ), + 'default' => '12', 'add' => '4.1', - 'title' => 'Contact Reference Autocomplete Options', + 'title' => 'Autocomplete Contact Search', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'Selected fields will be displayed in back-office autocomplete dropdown search results (Quick Search, etc.). Contact Name is always included.', 'help_text' => '', ), 'contact_reference_options' => array( @@ -437,32 +527,69 @@ function setting_getfields_expectedresult() { 'group' => 'core', 'name' => 'contact_reference_options', 'type' => 'String', - 'html_type' => 'checkboxes', + 'quick_form_type' => 'CheckBox', 'pseudoconstant' => array( - 'optionGroupName' => 'contact_reference_options', - ), - 'default' => array( - '0' => '1', - '1' => '2', - '2' => '3', - '3' => '4', - '4' => '5', - '5' => '6', - '6' => '7', + 'callback' => 'CRM_Admin_Form_Setting_Search::getContactReferenceOptions', ), + 'default' => '12', 'add' => '4.1', 'title' => 'Contact Reference Options', 'is_domain' => 1, 'is_contact' => 0, + 'description' => 'Selected fields will be displayed in autocomplete dropdown search results for \'Contact Reference\' custom fields. Contact Name is always included. NOTE: You must assign \'access contact reference fields\' permission to the anonymous role if you want to use custom contact reference fields in profiles on public pages. For most situations, you should use the \'Limit List to Group\' setting when configuring a contact reference field which will be used in public forms to prevent exposing your entire contact list.', + 'help_text' => '', + ), + 'contact_smart_group_display' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'contact_smart_group_display', + 'type' => 'String', + 'html_type' => 'radio', + 'default' => '1', + 'add' => '4.7', + 'title' => 'Viewing Smart Groups', + 'is_domain' => 1, + 'is_contact' => 0, 'description' => '', 'help_text' => '', ), + 'smart_group_cache_refresh_mode' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'smart_group_cache_refresh_mode', + 'type' => 'String', + 'html_type' => 'radio', + 'default' => 'opportunistic', + 'add' => '4.7', + 'title' => 'Smart Group Refresh Mode', + 'is_domain' => 1, + 'is_contact' => 0, + 'pseudoconstant' => array( + 'callback' => 'CRM_Contact_BAO_GroupContactCache::getModes', + ), + 'description' => 'Should the smart groups be by cron jobs or user actions', + 'help_text' => 'In \"Opportunistic Flush\" mode, caches are flushed in response to user actions; this mode is broadly compatible but may add latency during form-submissions. In \"Cron Flush\" mode, you should schedule a cron job to flush caches; this can improve latency on form-submissions but requires more setup.', + ), + 'installed' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'installed', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => '', + 'add' => '4.7', + 'title' => 'System Installed', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'A flag indicating whether this system has run a post-installation routine', + 'help_text' => '', + ), 'max_attachments' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'max_attachments', 'legacy_key' => 'maxAttachments', - 'prefetch' => 0, 'type' => 'Integer', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -482,8 +609,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'maxFileSize', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'Integer', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -535,21 +660,19 @@ function setting_getfields_expectedresult() { 'quick_form_type' => 'YesNo', 'default' => 1, 'add' => '4.4', - 'title' => 'Security Audits', + 'title' => 'Status Alerts', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'If enabled, CiviCRM will automatically run checks for significant mis-configurations such as ineffective file protections.', + 'description' => 'If enabled, CiviCRM will display pop-up notifications (no more than once per day) for security and misconfiguration issues identified in the system check.', 'help_text' => '', ), 'doNotAttachPDFReceipt' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'doNotAttachPDFReceipt', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'Boolean', 'quick_form_type' => 'YesNo', - 'default' => 1, + 'default' => 0, 'add' => '4.3', 'title' => 'Attach PDF copy to receipts', 'is_domain' => 1, @@ -561,8 +684,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'wkhtmltopdfPath', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -578,12 +699,29 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), + 'recaptchaOptions' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'recaptchaOptions', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_attributes' => array( + 'size' => 64, + 'maxlength' => 64, + ), + 'html_type' => 'Text', + 'default' => '', + 'add' => '4.3', + 'title' => 'Recaptcha Options', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'You can specify the reCAPTCHA theme options as comma separated data.(eg: theme:\'blackglass\', lang : \'fr\' ). Check the available options at <a href=\"https://developers.google.com/recaptcha/docs/display#config\">Customizing the Look and Feel of reCAPTCHA</a>.', + 'help_text' => '', + ), 'recaptchaPublicKey' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'recaptchaPublicKey', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -603,8 +741,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'recaptchaPrivateKey', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -620,11 +756,10 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), - 'checksumTimeout' => array( + 'checksum_timeout' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', - 'name' => 'checksumTimeout', - 'prefetch' => 1, + 'name' => 'checksum_timeout', 'type' => 'Integer', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -644,7 +779,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'blogUrl', - 'prefetch' => 0, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -664,7 +798,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'communityMessagesUrl', - 'prefetch' => 0, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -680,22 +813,35 @@ function setting_getfields_expectedresult() { 'description' => 'Service providing CiviCRM community messages', 'help_text' => 'Use \"*default*\" for the system default or override with a custom URL', ), - 'resCacheCode' => array( + 'gettingStartedUrl' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', - 'name' => 'resCacheCode', - 'prefetch' => 1, - 'config_only' => 1, + 'name' => 'gettingStartedUrl', 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( - 'size' => 16, - 'maxlength' => 16, + 'size' => 64, + 'maxlength' => 128, ), 'html_type' => 'Text', + 'default' => '*default*', + 'add' => '4.3', + 'title' => 'Getting Started URL', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Service providing the Getting Started data', + 'help_text' => 'Use \"*default*\" for the system default or override with a custom URL', + ), + 'resCacheCode' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'resCacheCode', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', 'default' => '', 'add' => '4.3', - 'title' => 'Resource Cache Code', + 'title' => 'resCacheCode', 'is_domain' => 1, 'is_contact' => 0, 'description' => 'Code appended to resource URLs (JS/CSS) to coerce HTTP caching', @@ -712,9 +858,23 @@ function setting_getfields_expectedresult() { 'title' => 'Verify SSL?', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'If disabled, backend HTTPS services will allow unverified, insecure connections', + 'description' => 'If disabled, outbound web-service requests will allow unverified, insecure HTTPS connections', 'help_text' => 'Unless you are absolutely unable to configure your server to check the SSL certificate of the remote server you should leave this set to Yes', ), + 'enableSSL' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'enableSSL', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.5', + 'title' => 'Force SSL?', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, inbound HTTP requests for sensitive pages will be redirected to HTTPS.', + 'help_text' => 'If enabled, inbound HTTP requests for sensitive pages will be redirected to HTTPS.', + ), 'wpBasePage' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', @@ -722,7 +882,6 @@ function setting_getfields_expectedresult() { 'type' => 'String', 'html_type' => 'text', 'quick_form_type' => 'Element', - 'prefetch' => 1, 'default' => '', 'add' => '4.3', 'title' => 'WordPress Base Page', @@ -735,7 +894,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'secondDegRelPermissions', - 'prefetch' => 1, 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 0, @@ -747,6 +905,7 @@ function setting_getfields_expectedresult() { 'help_text' => '', ), 'enable_components' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'enable_components', @@ -758,14 +917,7 @@ function setting_getfields_expectedresult() { 'style' => 'width:150px', 'class' => 'advmultiselect', ), - 'default' => array( - '0' => 'CiviEvent', - '1' => 'CiviContribute', - '2' => 'CiviMember', - '3' => 'CiviMail', - '4' => 'CiviReport', - '5' => 'CiviPledge', - ), + 'default' => '', 'add' => '4.4', 'title' => 'Enable Components', 'is_domain' => '1', @@ -796,7 +948,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'CiviCRM Preferences', 'group' => 'core', 'name' => 'empoweredBy', - 'prefetch' => 1, 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 1, @@ -807,176 +958,446 @@ function setting_getfields_expectedresult() { 'description' => 'When enabled, \"empowered by CiviCRM\" is displayed at the bottom of public forms.', 'help_text' => '', ), - 'userFrameworkLogging' => array( - 'group_name' => 'Developer Preferences', - 'group' => 'developer', - 'name' => 'userFrameworkLogging', + 'logging_no_trigger_permission' => array( + 'add' => '4.7', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'help_text' => '(EXPERIMENTAL) If the MySQL user does not have permission to administer triggers, then you must create the triggers outside CiviCRM. No support is provided for this configuration.', + 'name' => 'logging_no_trigger_permission', 'type' => 'Boolean', 'quick_form_type' => 'YesNo', + 'html_type' => '', 'default' => 0, - 'add' => '4.3', - 'title' => 'Enable Drupal Watchdog Logging', + 'title' => '(EXPERIMENTAL) MySQL user does not have trigger permissions', + 'description' => 'Set this when you intend to manage trigger creation outside of CiviCRM', + ), + 'logging' => array( + 'add' => '4.7', + 'help_text' => '', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'Set this value to Yes if you want CiviCRM error/debugging messages to appear in the Drupal error logs', - 'prefetch' => 1, - 'help_text' => 'Set this value to Yes if you want CiviCRM error/debugging messages the appear in your CMS\' error log. In the case of Drupal, this will cause all CiviCRM error messages to appear in the watchdog (assuming you have Drupal\'s watchdog enabled)', - ), - 'debug_enabled' => array( - 'group_name' => 'Developer Preferences', - 'group' => 'developer', - 'name' => 'debug_enabled', - 'config_key' => 'debug', + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'logging', 'type' => 'Boolean', 'quick_form_type' => 'YesNo', + 'html_type' => '', 'default' => 0, - 'add' => '4.3', - 'title' => 'Enable Debugging', + 'title' => 'Logging', + 'description' => 'If enabled, all actions will be logged with a complete record of changes.', + 'validate_callback' => 'CRM_Logging_Schema::checkLoggingSupport', + 'on_change' => array( + '0' => 'CRM_Logging_Schema::onToggle', + ), + ), + 'logging_uniqueid_date' => array( + 'add' => '4.7', + 'help_text' => 'This is the date when CRM-18193 was implemented', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'Set this value to Yes if you want to use one of CiviCRM\'s debugging tools. This feature should NOT be enabled for production sites', - 'prefetch' => 1, - 'help_text' => 'Do not turn this on on production sites', + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'logging_uniqueid_date', + 'type' => 'Date', + 'quick_form_type' => 'DateTime', + 'html_type' => '', + 'default' => '', + 'title' => 'Logging Unique ID not recorded before', + 'description' => 'This is the date when CRM-18193 was implemented', ), - 'backtrace' => array( - 'group_name' => 'Developer Preferences', - 'group' => 'developer', - 'name' => 'backtrace', + 'logging_all_tables_uniquid' => array( + 'add' => '4.7', + 'help_text' => 'This indicates there are no tables holdng pre-uniqid log_conn_id values (CRM-18193)', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'logging_all_tables_uniquid', 'type' => 'Boolean', 'quick_form_type' => 'YesNo', + 'html_type' => '', 'default' => 0, - 'add' => '4.3', - 'title' => 'Display Backtrace', + 'title' => 'All tables use Unique Connection ID', + 'description' => 'Do some tables pre-date CRM-18193?', + ), + 'userFrameworkUsersTableName' => array( + 'add' => '4.7', + 'help_text' => '', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'Set this value to Yes if you want to display a backtrace listing when a fatal error is encountered. This feature should NOT be enabled for production sites', - 'prefetch' => 1, - ), - 'fatalErrorHandler' => array( - 'group_name' => 'Developer Preferences', - 'group' => 'developer', - 'name' => 'fatalErrorHandler', + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'userFrameworkUsersTableName', 'type' => 'String', 'quick_form_type' => 'Element', 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '32', + 'maxlength' => '64', + ), 'default' => '', - 'add' => '4.3', + 'title' => 'Drupal Users Table Name', + 'description' => '', + ), + 'wpLoadPhp' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'wpLoadPhp', + 'type' => 'String', + 'html_type' => 'text', + 'quick_form_type' => 'Element', + 'default' => '', + 'add' => '4.6', + 'title' => 'WordPress Path to wp-load.php', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'CiviCRM will use this setting as path to bootstrap WP.', + 'help_text' => '', + ), + 'secure_cache_timeout_minutes' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'secure_cache_timeout_minutes', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 2, + 'maxlength' => 8, + ), + 'default' => 20, + 'add' => '4.7', + 'title' => 'Secure Cache Timeout', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Maximum number of minutes that secure form data should linger', + 'help_text' => '', + ), + 'site_id' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'site_id', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'default' => '', + 'add' => '4.6', + 'title' => 'Unique Site ID', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'systemStatusCheckResult' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'systemStatusCheckResult', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'default' => 0, + 'add' => '4.7', + 'title' => 'systemStatusCheckResult', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'recentItemsMaxCount' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'recentItemsMaxCount', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 2, + 'maxlength' => 3, + ), + 'default' => 20, + 'add' => '4.7', + 'title' => 'Size of \"Recent Items\" stack', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'How many items should CiviCRM store in it\'s \"Recently viewed\" list.', + 'help_text' => '', + ), + 'recentItemsProviders' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'recentItemsProviders', + 'type' => 'Array', + 'html_type' => 'Select', + 'quick_form_type' => 'Select', + 'html_attributes' => array( + 'multiple' => 1, + 'class' => 'crm-select2', + ), + 'default' => '', + 'add' => '4.7', + 'title' => 'Recent Items Providers', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'What providers may save views in CiviCRM\'s \"Recently viewed\" list. If empty, all are in.', + 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Utils_Recent::getProviders', + ), + ), + 'dedupe_default_limit' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'dedupe_default_limit', + 'type' => 'Integer', + 'default' => 0, + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'add' => '4.7', + 'title' => 'Default limit for dedupe screen', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Default to only loading matches against this number of contacts', + 'help_text' => 'Deduping larger databases can crash the server. By configuring a limit other than 0 here the dedupe query will only search for matches against a limited number of contacts.', + ), + 'syncCMSEmail' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'syncCMSEmail', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.7', + 'title' => 'Sync CMS Email', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, then CMS email id will be syncronised with CiviCRM contacts\'s primary email.', + 'help_text' => '', + ), + 'userFrameworkLogging' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'userFrameworkLogging', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.3', + 'title' => 'Enable Drupal Watchdog Logging', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Set this value to Yes if you want CiviCRM error/debugging messages to appear in the Drupal error logs', + 'help_text' => 'Set this value to Yes if you want CiviCRM error/debugging messages the appear in your CMS\' error log. In the case of Drupal, this will cause all CiviCRM error messages to appear in the watchdog (assuming you have Drupal\'s watchdog enabled)', + ), + 'debug_enabled' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'debug_enabled', + 'config_key' => 'debug', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.3', + 'title' => 'Enable Debugging', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Set this value to Yes if you want to use one of CiviCRM\'s debugging tools. This feature should NOT be enabled for production sites', + 'help_text' => 'Do not turn this on on production sites', + ), + 'backtrace' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'backtrace', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.3', + 'title' => 'Display Backtrace', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Set this value to Yes if you want to display a backtrace listing when a fatal error is encountered. This feature should NOT be enabled for production sites', + ), + 'fatalErrorHandler' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'fatalErrorHandler', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'default' => '', + 'add' => '4.3', 'title' => 'Fatal Error Handler', 'is_domain' => 1, 'is_contact' => 0, 'description' => 'Enter the path and class for a custom PHP error-handling function if you want to override built-in CiviCRM error handling for your site.', - 'prefetch' => 1, ), 'uploadDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'uploadDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, - 'title' => 'Upload Directory', + 'title' => 'Temporary Files Directory', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', - 'help_text' => '', + 'help_text' => 'File system path where temporary CiviCRM files - such as import data files - are uploaded.', ), 'imageUploadDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'imageUploadDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'title' => 'Image Directory', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'File system path where image files are uploaded. Currently, this path is used for images associated with premiums (CiviContribute thank-you gifts).', 'help_text' => '', ), 'customFileUploadDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'customFileUploadDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, - 'title' => 'Custom Files Upload Directory', + 'title' => 'Custom Files Directory', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'Path where documents and images which are attachments to contact records are stored (e.g. contact photos, resumes, contracts, etc.). These attachments are defined using \'file\' type custom fields.', 'help_text' => '', ), 'customTemplateDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'customTemplateDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'title' => 'Custom Template Directory', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'Path where site specific templates are stored if any. This directory is searched first if set. Custom JavaScript code can be added to templates by creating files named templateFile.extra.tpl. (learn more...)', 'help_text' => '', ), 'customPHPPathDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'customPHPPathDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, - 'title' => 'Custom PHP Path', + 'title' => 'Custom PHP Directory', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'Path where site specific PHP code files are stored if any. This directory is searched first if set.', 'help_text' => '', ), 'extensionsDir' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group_name' => 'Directory Preferences', 'group' => 'directory', 'name' => 'extensionsDir', - 'type' => 'Url', + 'type' => 'String', 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'title' => 'Extensions Directory', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', + 'description' => 'Path where CiviCRM extensions are stored.', 'help_text' => '', ), - 'event_enable_cart' => array( + 'enable_cart' => array( 'name' => 'enable_cart', 'group_name' => 'Event Preferences', 'group' => 'event', - 'type' => 'String', + 'type' => 'Boolean', 'quick_form_type' => 'Element', 'default' => 0, 'add' => '4.1', 'title' => 'Enable Event Cart', 'is_domain' => 1, - 'is_contact' => 1, + 'is_contact' => 0, 'description' => 'WRITE ME', 'help_text' => 'WRITE ME', ), + 'show_events' => array( + 'name' => 'show_events', + 'group_name' => 'Event Preferences', + 'group' => 'event', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'default' => 10, + 'add' => '4.5', + 'title' => 'Dashboard entries', + 'html_type' => 'select', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Configure how many events should be shown on the dashboard. This overrides the default value of 10 entries.', + 'help_text' => '', + ), + 'ext_repo_url' => array( + 'group_name' => 'Extension Preferences', + 'group' => 'ext', + 'name' => 'ext_repo_url', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_attributes' => array( + 'size' => 64, + 'maxlength' => 128, + ), + 'html_type' => 'Text', + 'default' => 'https://civicrm.org/extdir/ver={ver}|cms={uf}', + 'add' => '4.3', + 'title' => 'Extension Repo URL', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'customTranslateFunction' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'customTranslateFunction', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '30', + 'maxlength' => '100', + ), + 'default' => '', + 'title' => 'Custom Translate Function', + 'description' => '', + ), 'monetaryThousandSeparator' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'monetaryThousandSeparator', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -995,8 +1416,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'monetaryDecimalPoint', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -1015,8 +1434,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'moneyformat', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -1032,14 +1449,12 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'moneyvalueformat', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', 'quick_form_type' => 'Element', 'html_type' => 'text', 'default' => '%!i', 'add' => '4.3', - 'title' => 'Monetary Amount Display', + 'title' => 'Monetary Value Display', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', @@ -1049,13 +1464,11 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'defaultCurrency', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', - 'quick_form_type' => 'Element', - 'html_type' => 'text', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', 'html_attributes' => array( - 'size' => 2, + 'class' => 'crm-select2', ), 'default' => 'USD', 'add' => '4.3', @@ -1064,19 +1477,18 @@ function setting_getfields_expectedresult() { 'is_contact' => 0, 'description' => 'Default currency assigned to contributions and other monetary transactions.', 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getCurrencySymbols', + ), ), 'defaultContactCountry' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'defaultContactCountry', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', - 'quick_form_type' => 'Element', - 'html_type' => 'text', - 'html_attributes' => array( - 'size' => 4, - ), + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array(), 'default' => '1228', 'add' => '4.4', 'title' => 'Default Country', @@ -1084,13 +1496,29 @@ function setting_getfields_expectedresult() { 'is_contact' => 0, 'description' => 'This value is selected by default when adding a new contact address.', 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getAvailableCountries', + ), + ), + 'defaultContactStateProvince' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'defaultContactStateProvince', + 'type' => 'Integer', + 'quick_form_type' => 'ChainSelect', + 'html_type' => 'ChainSelect', + 'default' => '', + 'title' => 'Default State/Province', + 'description' => 'This value is selected by default when adding a new contact address.', ), 'countryLimit' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'countryLimit', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'Array', 'quick_form_type' => 'Element', 'html_type' => 'advmultiselect', @@ -1099,20 +1527,21 @@ function setting_getfields_expectedresult() { 'style' => 'width:150px', 'class' => 'advmultiselect', ), - 'default' => 'null', + 'default' => array(), 'add' => '4.3', 'title' => 'Available Countries', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getAvailableCountries', + ), ), 'provinceLimit' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'provinceLimit', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'Array', 'quick_form_type' => 'Element', 'html_type' => 'advmultiselect', @@ -1121,20 +1550,21 @@ function setting_getfields_expectedresult() { 'style' => 'width:150px', 'class' => 'advmultiselect', ), - 'default' => 'null', + 'default' => array(), 'add' => '4.3', - 'title' => 'Available States and Provinces', + 'title' => 'Available States and Provinces (by Country)', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getAvailableCountries', + ), ), 'inheritLocale' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'inheritLocale', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 0, @@ -1149,12 +1579,12 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'dateformatDatetime', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', 'default' => '%B %E%f, %Y %l:%M %P', 'add' => '4.3', - 'title' => 'Complete Date and Time', + 'title' => 'Date Format: Complete Date and Time', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', @@ -1164,12 +1594,12 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'dateformatFull', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', 'default' => '%B %E%f, %Y', 'add' => '4.3', - 'title' => 'Complete Date', + 'title' => 'Date Format: Complete Date', 'is_domain' => 1, 'is_contact' => 0, 'description' => '', @@ -1179,31 +1609,272 @@ function setting_getfields_expectedresult() { 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'dateformatPartial', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', 'default' => '%B %Y', 'add' => '4.3', - 'title' => 'Month and Year', + 'title' => 'Date Format: Month and Year', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'dateformatTime' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'dateformatTime', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '12', + 'maxlength' => '60', + ), + 'default' => '%l:%M %P', + 'title' => 'Date Format: Time Only', + 'description' => '', + ), + 'dateformatYear' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'dateformatYear', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '12', + 'maxlength' => '60', + ), + 'default' => '%Y', + 'title' => 'Date Format: Year Only', + 'description' => '', + ), + 'dateformatFinancialBatch' => array( + 'add' => '4.7', + 'help_text' => '', 'is_domain' => 1, 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'dateformatFinancialBatch', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '12', + 'maxlength' => '60', + ), + 'default' => '%m/%d/%Y', + 'title' => 'Date Format: Financial Batch', 'description' => '', + ), + 'dateformatshortdate' => array( + 'add' => '4.7', 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'dateformatshortdate', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '12', + 'maxlength' => '60', + ), + 'default' => '%m/%d/%Y', + 'title' => 'Date Format: Short date Month Day Year', + 'description' => '', + ), + 'dateInputFormat' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'dateInputFormat', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_SelectValues::getDatePluginInputFormats', + ), + 'default' => 'mm/dd/yy', + 'title' => 'Date Input Format', + 'description' => '', + ), + 'fieldSeparator' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'fieldSeparator', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '2', + 'maxlength' => '8', + ), + 'default' => ',', + 'title' => 'Import / Export Field Separator', + 'description' => 'Global CSV separator character. Modify this setting to enable import and export of different kinds of CSV files (for example: \',\' \';\' \':\' \'|\' ).', + ), + 'fiscalYearStart' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'fiscalYearStart', + 'type' => 'Array', + 'quick_form_type' => 'MonthDay', + 'html_type' => 'MonthDay', + 'default' => array( + 'M' => 1, + 'd' => 1, + ), + 'title' => 'Fiscal Year Start', + 'description' => '', + ), + 'languageLimit' => array( + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'languageLimit', + 'type' => 'Array', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'multiple' => 1, + 'class' => 'crm-select2', + ), + 'default' => '', + 'add' => '4.3', + 'title' => 'Available Languages (Multi-lingual)', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_I18n::languages', + ), ), 'lcMessages' => array( 'group_name' => 'Localization Preferences', 'group' => 'localization', 'name' => 'lcMessages', - 'prefetch' => 1, - 'config_only' => 1, 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), 'default' => 'en_US', 'add' => '4.3', 'title' => 'Default Language', 'is_domain' => 1, 'is_contact' => 0, - 'description' => '', - 'help_text' => '', + 'description' => '', + 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions', + ), + 'on_change' => array( + '0' => 'CRM_Admin_Form_Setting_Localization::onChangeLcMessages', + ), + ), + 'legacyEncoding' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'legacyEncoding', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '12', + 'maxlength' => '30', + ), + 'default' => 'Windows-1252', + 'title' => 'Legacy Encoding', + 'description' => 'If import files are NOT encoded as UTF-8, specify an alternate character encoding for these files. The default of Windows-1252 will work for Excel-created .CSV files on many computers.', + ), + 'timeInputFormat' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'timeInputFormat', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_SelectValues::getTimeFormats', + ), + 'default' => '1', + 'title' => 'Time Input Format', + 'description' => '', + 'on_change' => array( + '0' => 'CRM_Core_BAO_PreferencesDate::onChangeSetting', + ), + ), + 'weekBegins' => array( + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'weekBegins', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'pseudoconstant' => array( + 'callback' => 'CRM_Utils_Date::getFullWeekdayNames', + ), + 'default' => 0, + 'add' => '4.7', + 'title' => 'Week begins on', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'contact_default_language' => array( + 'group_name' => 'Localization Preferences', + 'group' => 'localization', + 'name' => 'contact_default_language', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Localization::getDefaultLanguageOptions', + ), + 'default' => '*default*', + 'add' => '4.7', + 'title' => 'Default Language for contacts', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Default language (if any) for contact records', + 'help_text' => 'If a contact is created with no language this setting will determine the language data (if any) to save.You may or may not wish to make an assumption here about whether it matches the site language', ), 'profile_double_optin' => array( 'group_name' => 'Mailing Preferences', @@ -1211,7 +1882,7 @@ function setting_getfields_expectedresult() { 'name' => 'profile_double_optin', 'type' => 'Integer', 'html_type' => 'checkbox', - 'default' => 0, + 'default' => '1', 'add' => '4.1', 'title' => 'Enable Double Opt-in for Profile Group(s) field', 'is_domain' => 1, @@ -1262,13 +1933,29 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), + 'replyTo' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'replyTo', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.6', + 'title' => 'Enable Custom Reply-To', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Allow CiviMail users to send mailings with a custom Reply-To header', + 'help_text' => '', + ), 'mailing_backend' => array( 'group_name' => 'Mailing Preferences', 'group' => 'mailing', 'name' => 'mailing_backend', 'type' => 'Array', 'html_type' => 'checkbox', - 'default' => 0, + 'default' => array( + 'outBound_option' => '3', + ), 'add' => '4.1', 'title' => 'Mailing Backend', 'is_domain' => 1, @@ -1332,6 +2019,223 @@ function setting_getfields_expectedresult() { 'description' => 'If enabled, a randomized hash key will be used to reference the mailing URL in the mailing.viewUrl token, instead of the mailing ID', 'help_text' => '', ), + 'civimail_multiple_bulk_emails' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'civimail_multiple_bulk_emails', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'default' => 0, + 'add' => '4.5', + 'title' => ' Multiple Bulk Emails', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, CiviMail will deliver a copy of the email to each bulk email listed for the contact.', + 'help_text' => '', + ), + 'include_message_id' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'include_message_id', + 'type' => 'Integer', + 'html_type' => 'checkbox', + 'default' => '', + 'add' => '4.5', + 'title' => 'Enable CiviMail to generate Message-ID header', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'mailerBatchLimit' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'mailerBatchLimit', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 0, + 'add' => '4.7', + 'title' => 'Mailer Batch Limit', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Throttle email delivery by setting the maximum number of emails sent during each CiviMail run (0 = unlimited).', + 'help_text' => '', + ), + 'mailerJobSize' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'mailerJobSize', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 0, + 'add' => '4.7', + 'title' => 'Mailer Job Size', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If you want to utilize multi-threading enter the size you want your sub jobs to be split into. Recommended values are between 1,000 and 10,000. Use a lower value if your server has multiple cron jobs running simultaneously, but do not use values smaller than 1,000. Enter \"0\" to disable multi-threading and process mail as one single job - batch limits still apply.', + 'help_text' => '', + ), + 'mailerJobsMax' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'mailerJobsMax', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 0, + 'add' => '4.7', + 'title' => 'Mailer Cron Job Limit', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'The maximum number of mailer delivery jobs executing simultaneously (0 = allow as many processes to execute as started by cron)', + 'help_text' => '', + ), + 'mailThrottleTime' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'mailThrottleTime', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 0, + 'add' => '4.7', + 'title' => 'Mailer Throttle Time', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'The time to sleep in between each e-mail in micro seconds. Setting this above 0 allows you to control the rate at which e-mail messages are sent to the mail server, avoiding filling up the mail queue very quickly. Set to 0 to disable.', + 'help_text' => '', + ), + 'verpSeparator' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'verpSeparator', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 32, + ), + 'default' => '.', + 'add' => '4.7', + 'title' => 'VERP Separator', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Separator character used when CiviMail generates VERP (variable envelope return path) Mail-From addresses.', + 'help_text' => '', + ), + 'write_activity_record' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'write_activity_record', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => '1', + 'add' => '4.7', + 'title' => 'Enable CiviMail to create activities on delivery', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => '', + 'help_text' => '', + ), + 'geoAPIKey' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Map Preferences', + 'group' => 'map', + 'name' => 'geoAPIKey', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '32', + 'maxlength' => '64', + ), + 'default' => '', + 'title' => 'Geo Provider Key', + 'description' => 'Enter the API key or Application ID associated with your geocoding provider (not required for Yahoo).', + ), + 'geoProvider' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Map Preferences', + 'group' => 'map', + 'name' => 'geoProvider', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_SelectValues::geoProvider', + ), + 'default' => '', + 'title' => 'Geocoding Provider', + 'description' => 'You may choose a different webservice for geocoding. This is required if there is no geo-coding plugin for your selected mapping provider. You can leave the Geocoding fields blank if you are using Google as your mapping provider.', + ), + 'mapAPIKey' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Map Preferences', + 'group' => 'map', + 'name' => 'mapAPIKey', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => '32', + 'maxlength' => '64', + ), + 'default' => '', + 'title' => 'Map Provider Key', + 'description' => 'Enter your API Key or Application ID. An API Key is currently optional for Google Maps API, but may be helpful diagnosing any problems and required for higher volumes of requests. Refer to developers.google.com for the latest information.', + ), + 'mapProvider' => array( + 'add' => '4.7', + 'help_text' => '', + 'is_domain' => 1, + 'is_contact' => 0, + 'group_name' => 'Map Preferences', + 'group' => 'map', + 'name' => 'mapProvider', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), + 'pseudoconstant' => array( + 'callback' => 'CRM_Core_SelectValues::mapProvider', + ), + 'default' => '', + 'title' => 'Mapping Provider', + 'description' => 'Choose the mapping provider that has the best coverage for the majority of your contact addresses.', + ), 'default_renewal_contribution_page' => array( 'group_name' => 'Member Preferences', 'group' => 'member', @@ -1355,7 +2259,7 @@ function setting_getfields_expectedresult() { 'name' => 'is_enabled', 'title' => 'Multisite Is enabled', 'type' => 'Integer', - 'default' => '', + 'default' => 0, 'add' => '4.1', 'is_domain' => 1, 'is_contact' => 0, @@ -1368,7 +2272,7 @@ function setting_getfields_expectedresult() { 'name' => 'domain_group_id', 'title' => 'Multisite Domain Group', 'type' => 'Integer', - 'default' => '', + 'default' => 0, 'add' => '4.1', 'is_domain' => 1, 'is_contact' => 0, @@ -1381,7 +2285,7 @@ function setting_getfields_expectedresult() { 'name' => 'event_price_set_domain_id', 'title' => 'Domain Event Price Set', 'type' => 'Integer', - 'default' => '', + 'default' => 0, 'add' => '4.1', 'is_domain' => 1, 'is_contact' => 0, @@ -1394,7 +2298,7 @@ function setting_getfields_expectedresult() { 'name' => 'uniq_email_per_site', 'type' => 'Integer', 'title' => 'Unique Email per Domain?', - 'default' => '', + 'default' => 0, 'add' => '4.1', 'is_domain' => 1, 'is_contact' => 0, @@ -1405,7 +2309,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'Search Preferences', 'group' => 'Search Preferences', 'name' => 'search_autocomplete_count', - 'prefetch' => 0, 'type' => 'Integer', 'quick_form_type' => 'Element', 'html_type' => 'text', @@ -1425,7 +2328,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'Search Preferences', 'group' => 'Search Preferences', 'name' => 'enable_innodb_fts', - 'prefetch' => 0, 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 0, @@ -1446,7 +2348,6 @@ function setting_getfields_expectedresult() { 'group_name' => 'Search Preferences', 'group' => 'Search Preferences', 'name' => 'fts_query_mode', - 'prefetch' => 0, 'type' => 'String', 'quick_form_type' => 'Element', 'html_attributes' => array( @@ -1462,50 +2363,179 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), + 'includeOrderByClause' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'includeOrderByClause', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.6', + 'title' => 'Include Order By Clause', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If disabled, the search results will not be ordered. This may improve response time on search results on large datasets', + 'help_text' => '', + ), + 'includeWildCardInName' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'includeWildCardInName', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.6', + 'title' => 'Automatic Wildcard', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, wildcards are automatically added to the beginning AND end of the search term when users search for contacts by Name. EXAMPLE: Searching for \'ada\' will return any contact whose name includes those letters - e.g. \'Adams, Janet\', \'Nadal, Jorge\', etc. If disabled, a wildcard is added to the end of the search term only. EXAMPLE: Searching for \'ada\' will return any contact whose last name begins with those letters - e.g. \'Adams, Janet\' but NOT \'Nadal, Jorge\'. Disabling this feature will speed up search significantly for larger databases, but users must manually enter wildcards (\'%\' or \'_\') to the beginning of the search term if they want to find all records which contain those letters. EXAMPLE: \'%ada\' will return \'Nadal, Jorge\'.', + 'help_text' => '', + ), + 'includeEmailInName' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'includeEmailInName', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.6', + 'title' => 'Include Email', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, email addresses are automatically included when users search by Name. Disabling this feature will speed up search significantly for larger databases, but users will need to use the Email search fields (from Advanced Search, Search Builder, or Profiles) to find contacts by email address.', + 'help_text' => '', + ), + 'includeNickNameInName' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'includeNickNameInName', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 0, + 'add' => '4.6', + 'title' => 'Include Nickname', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, nicknames are automatically included when users search by Name.', + 'help_text' => '', + ), + 'includeAlphabeticalPager' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'includeAlphabeticalPager', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.6', + 'title' => 'Include Alphabetical Pager', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If disabled, the alphabetical pager will not be displayed on the search screens. This will improve response time on search results on large datasets.', + 'help_text' => '', + ), + 'smartGroupCacheTimeout' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'smartGroupCacheTimeout', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'default' => 5, + 'add' => '4.6', + 'title' => 'Smart group cache timeout', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'The number of minutes to cache smart group contacts. We strongly recommend that this value be greater than zero, since a value of zero means no caching at all. If your contact data changes frequently, you should set this value to at least 5 minutes.', + 'help_text' => '', + ), + 'defaultSearchProfileID' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'defaultSearchProfileID', + 'type' => 'Integer', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), + 'pseudoconstant' => array( + 'callback' => 'CRM_Admin_Form_Setting_Search::getAvailableProfiles', + ), + 'default' => '', + 'add' => '4.6', + 'title' => 'Default Contact Search Profile', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If set, this will be the default profile used for contact search.', + 'help_text' => '', + ), 'userFrameworkResourceURL' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group' => 'url', 'group_name' => 'URL Preferences', 'name' => 'userFrameworkResourceURL', - 'title' => 'Script and CSS Resources URL', + 'title' => 'CiviCRM Resource URL', 'type' => 'String', + 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'CiviCRM Resource URL', + 'description' => 'Absolute URL of the location where the civicrm module or component has been installed.', 'help_text' => '', - 'validate_callback' => 'CRM_Utils_Rule::url', + 'validate_callback' => 'CRM_Utils_Rule::urlish', ), 'imageUploadURL' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group' => 'url', 'group_name' => 'URL Preferences', - 'title' => 'Image URL Prefix', + 'title' => 'Image Upload URL', 'name' => 'imageUploadURL', 'type' => 'String', + 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'Image Upload URL', + 'description' => 'URL of the location for uploaded image files.', 'help_text' => '', - 'validate_callback' => 'CRM_Utils_Rule::url', + 'validate_callback' => 'CRM_Utils_Rule::urlish', ), 'customCSSURL' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group' => 'url', 'group_name' => 'URL Preferences', 'name' => 'customCSSURL', - 'title' => 'Custom CSS', + 'title' => 'Custom CSS URL', 'type' => 'String', + 'html_type' => 'Text', + 'quick_form_type' => 'Element', 'default' => '', 'add' => '4.1', - 'prefetch' => 1, 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'Custom CiviCRM CSS URL', + 'description' => 'You can modify the look and feel of CiviCRM by adding your own stylesheet. For small to medium sized modifications, use your css file to override some of the styles in civicrm.css. Or if you need to make drastic changes, you can choose to disable civicrm.css completely.', 'help_text' => '', - 'validate_callback' => 'CRM_Utils_Rule::url', + 'validate_callback' => 'CRM_Utils_Rule::urlish', + ), + 'extensionsURL' => array( + 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', + 'group' => 'url', + 'group_name' => 'URL Preferences', + 'title' => 'Extension Resource URL', + 'name' => 'extensionsURL', + 'type' => 'String', + 'html_type' => 'Text', + 'quick_form_type' => 'Element', + 'default' => '', + 'add' => '4.1', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Base URL for extension resources (images, stylesheets, etc). This should match extensionsDir.', + 'help_text' => '', + 'validate_callback' => 'CRM_Utils_Rule::urlish', ), ), ); diff --git a/civicrm/api/v3/examples/Setting/GetSettingCurrentDomain.php b/civicrm/api/v3/examples/Setting/GetSettingCurrentDomain.php index 5ace770b00abde215966fd6915f041a66ee04f8b..3b465448174d8bd9cc79610a92d880534e6c6443 100644 --- a/civicrm/api/v3/examples/Setting/GetSettingCurrentDomain.php +++ b/civicrm/api/v3/examples/Setting/GetSettingCurrentDomain.php @@ -21,7 +21,8 @@ function setting_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/GetSpecifiedDomains.php b/civicrm/api/v3/examples/Setting/GetSpecifiedDomains.php index 683e6618b3eb5eabacb0dd0c7428397f903be688..ef6db54e00254e97ee5ee87f84b604f205e5dd8f 100644 --- a/civicrm/api/v3/examples/Setting/GetSpecifiedDomains.php +++ b/civicrm/api/v3/examples/Setting/GetSpecifiedDomains.php @@ -27,7 +27,8 @@ function setting_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/GetValue.php b/civicrm/api/v3/examples/Setting/GetValue.php index 8ee9aa41f253cf2617b76e6af33ad1468fb3b301..10991cc435bb1d8fb872dd673e90a1251e32c90a 100644 --- a/civicrm/api/v3/examples/Setting/GetValue.php +++ b/civicrm/api/v3/examples/Setting/GetValue.php @@ -22,7 +22,8 @@ function setting_getvalue_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Setting/Revert.php b/civicrm/api/v3/examples/Setting/Revert.php index 9eb77d993e15245e6b153ea54302e0d08eedfe76..40631b92af01345de5646a3b8ac27cea27ca7404 100644 --- a/civicrm/api/v3/examples/Setting/Revert.php +++ b/civicrm/api/v3/examples/Setting/Revert.php @@ -21,7 +21,8 @@ function setting_revert_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/StateProvince/Create.php b/civicrm/api/v3/examples/StateProvince/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..d8e8e56d0c43ecbe3b61c10cf56948c0ff0f2aa8 --- /dev/null +++ b/civicrm/api/v3/examples/StateProvince/Create.php @@ -0,0 +1,80 @@ +<?php +/** + * Test Generated example demonstrating the StateProvince.create API. + * + * @return array + * API result array + */ +function state_province_create_example() { + $params = array( + 'name' => 'Wessex', + 'abbreviation' => 'WEX', + 'country_id' => 1226, + ); + + try{ + $result = civicrm_api3('StateProvince', 'create', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function state_province_create_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 13947, + 'values' => array( + '13947' => array( + 'id' => '13947', + 'name' => 'Wessex', + 'abbreviation' => 'WEX', + 'country_id' => '1226', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreateStateProvince" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StateProvinceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/StateProvince/Delete.php b/civicrm/api/v3/examples/StateProvince/Delete.php new file mode 100644 index 0000000000000000000000000000000000000000..6d3d142420326659764cc1a3bad7fb2dcfc4469f --- /dev/null +++ b/civicrm/api/v3/examples/StateProvince/Delete.php @@ -0,0 +1,70 @@ +<?php +/** + * Test Generated example demonstrating the StateProvince.delete API. + * + * @return array + * API result array + */ +function state_province_delete_example() { + $params = array( + 'id' => 13948, + ); + + try{ + $result = civicrm_api3('StateProvince', 'delete', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function state_province_delete_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'values' => 1, + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testDeleteStateProvince" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StateProvinceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/StateProvince/Get.php b/civicrm/api/v3/examples/StateProvince/Get.php new file mode 100644 index 0000000000000000000000000000000000000000..c4f1ace0fb38afca00cb49b1e62932454da6ae18 --- /dev/null +++ b/civicrm/api/v3/examples/StateProvince/Get.php @@ -0,0 +1,78 @@ +<?php +/** + * Test Generated example demonstrating the StateProvince.get API. + * + * @return array + * API result array + */ +function state_province_get_example() { + $params = array( + 'name' => 'Wessex', + ); + + try{ + $result = civicrm_api3('StateProvince', 'get', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function state_province_get_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 13949, + 'values' => array( + '13949' => array( + 'id' => '13949', + 'name' => 'Wessex', + 'abbreviation' => 'WEX', + 'country_id' => '1226', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testGet" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StateProvinceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/StatusPreference/Create.php b/civicrm/api/v3/examples/StatusPreference/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..01ae882c12d3f711936ded4f18f70cde3e87452b --- /dev/null +++ b/civicrm/api/v3/examples/StatusPreference/Create.php @@ -0,0 +1,85 @@ +<?php +/** + * Test Generated example demonstrating the StatusPreference.create API. + * + * @return array + * API result array + */ +function status_preference_create_example() { + $params = array( + 'name' => 'test_check', + 'domain_id' => 1, + 'hush_until' => '20151212', + 'ignore_severity' => 'cRItical', + 'check_info' => '', + ); + + try{ + $result = civicrm_api3('StatusPreference', 'create', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function status_preference_create_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 4, + 'values' => array( + '4' => array( + 'id' => '4', + 'domain_id' => '1', + 'name' => 'test_check', + 'hush_until' => '20151212000000', + 'ignore_severity' => '5', + 'prefs' => '', + 'check_info' => '', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testCreateSeverityByName" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StatusPreferenceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/StatusPreference/Delete.php b/civicrm/api/v3/examples/StatusPreference/Delete.php new file mode 100644 index 0000000000000000000000000000000000000000..8c3d75f6770066bfc624a1578075c00a16aa48a0 --- /dev/null +++ b/civicrm/api/v3/examples/StatusPreference/Delete.php @@ -0,0 +1,70 @@ +<?php +/** + * Test Generated example demonstrating the StatusPreference.delete API. + * + * @return array + * API result array + */ +function status_preference_delete_example() { + $params = array( + 'id' => 2, + ); + + try{ + $result = civicrm_api3('StatusPreference', 'delete', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function status_preference_delete_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'values' => 1, + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testDeleteStatusPreference" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StatusPreferenceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/StatusPreference/Get.php b/civicrm/api/v3/examples/StatusPreference/Get.php new file mode 100644 index 0000000000000000000000000000000000000000..b1334a9cae359b89268ea90159777a7ed1dc8e03 --- /dev/null +++ b/civicrm/api/v3/examples/StatusPreference/Get.php @@ -0,0 +1,79 @@ +<?php +/** + * Test Generated example demonstrating the StatusPreference.get API. + * + * @return array + * API result array + */ +function status_preference_get_example() { + $params = array( + 'id' => 3, + ); + + try{ + $result = civicrm_api3('StatusPreference', 'get', $params); + } + catch (CiviCRM_API3_Exception $e) { + // Handle error here. + $errorMessage = $e->getMessage(); + $errorCode = $e->getErrorCode(); + $errorData = $e->getExtraParams(); + return array( + 'is_error' => 1, + 'error_message' => $errorMessage, + 'error_code' => $errorCode, + 'error_data' => $errorData, + ); + } + + return $result; +} + +/** + * Function returns array of result expected from previous function. + * + * @return array + * API result array + */ +function status_preference_get_expectedresult() { + + $expectedResult = array( + 'is_error' => 0, + 'version' => 3, + 'count' => 1, + 'id' => 3, + 'values' => array( + '3' => array( + 'id' => '3', + 'domain_id' => '1', + 'name' => 'test_check', + 'hush_until' => '2015-12-12', + 'ignore_severity' => '4', + ), + ), + ); + + return $expectedResult; +} + +/* +* This example has been generated from the API test suite. +* The test that created it is called "testStatusPreferenceGet" +* and can be found at: +* https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/StatusPreferenceTest.php +* +* You can see the outcome of the API tests at +* https://test.civicrm.org/job/CiviCRM-master-git/ +* +* To Learn about the API read +* http://wiki.civicrm.org/confluence/display/CRMDOC/Using+the+API +* +* Browse the api on your own site with the api explorer +* http://MYSITE.ORG/path/to/civicrm/api +* +* Read more about testing here +* http://wiki.civicrm.org/confluence/display/CRM/Testing +* +* API Standards documentation: +* http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards +*/ diff --git a/civicrm/api/v3/examples/Survey/ChainedGetDelete.php b/civicrm/api/v3/examples/Survey/ChainedGetDelete.php index 2a218305a4f753a58f45d50139d78d6331c20c08..860366008bd5dee54826408773d33e276ccd91c4 100644 --- a/civicrm/api/v3/examples/Survey/ChainedGetDelete.php +++ b/civicrm/api/v3/examples/Survey/ChainedGetDelete.php @@ -22,7 +22,8 @@ function survey_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -60,7 +61,7 @@ function survey_get_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ), ), ), diff --git a/civicrm/api/v3/examples/Survey/Create.php b/civicrm/api/v3/examples/Survey/Create.php index 11a84829142f611555f30d67fc7faabdea8d5731..09a73872516cb1334f61e4ebf5b7a021b6fa8fbb 100644 --- a/civicrm/api/v3/examples/Survey/Create.php +++ b/civicrm/api/v3/examples/Survey/Create.php @@ -22,7 +22,8 @@ function survey_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Survey/Delete.php b/civicrm/api/v3/examples/Survey/Delete.php index b2b7f6d1a6d860201f7235f60f3291cbd106a9ba..2a15ecb7be4384368ac454bad23df963be3274e9 100644 --- a/civicrm/api/v3/examples/Survey/Delete.php +++ b/civicrm/api/v3/examples/Survey/Delete.php @@ -19,7 +19,8 @@ function survey_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function survey_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/Survey/Get.php b/civicrm/api/v3/examples/Survey/Get.php index 43038c18303d61f0ac3012b1315dcb113a925342..f1c14e1b4416759245ddb047407e15dd3aff580e 100644 --- a/civicrm/api/v3/examples/Survey/Get.php +++ b/civicrm/api/v3/examples/Survey/Get.php @@ -22,7 +22,8 @@ function survey_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/SurveyRespondant/Get.php b/civicrm/api/v3/examples/SurveyRespondant/Get.php index b07f6a770f730ece8992604d74a0b2bbeacc2ccb..93614aacf45ed2bc28235edce61e65c97754fd9b 100644 --- a/civicrm/api/v3/examples/SurveyRespondant/Get.php +++ b/civicrm/api/v3/examples/SurveyRespondant/Get.php @@ -23,7 +23,8 @@ function survey_respondant_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/System/Flush.php b/civicrm/api/v3/examples/System/Flush.php index 0d124c21444f77aeb58bf1801ddbd1648108dad8..dab2f325a42a780b08ffbc2a4361d4f86cf674cc 100644 --- a/civicrm/api/v3/examples/System/Flush.php +++ b/civicrm/api/v3/examples/System/Flush.php @@ -19,7 +19,8 @@ function system_flush_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Tag/Create.php b/civicrm/api/v3/examples/Tag/Create.php index 503eacabdb8a1eec2fd0811b052e0c06475c63f2..3add021f743f166f4ff4ad47b2f4299b781aea32 100644 --- a/civicrm/api/v3/examples/Tag/Create.php +++ b/civicrm/api/v3/examples/Tag/Create.php @@ -20,7 +20,8 @@ function tag_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -53,6 +54,7 @@ function tag_create_expectedresult() { 'is_tagset' => '', 'used_for' => 'civicrm_contact', 'created_id' => '', + 'color' => '', 'created_date' => '2013-07-28 08:49:19', ), ), diff --git a/civicrm/api/v3/examples/Tag/Delete.php b/civicrm/api/v3/examples/Tag/Delete.php index b1112ad56bd2318e101a3ff58a4ac26776ce5a5f..75f072716aa16e9cc1dd61b9885f074a692bc459 100644 --- a/civicrm/api/v3/examples/Tag/Delete.php +++ b/civicrm/api/v3/examples/Tag/Delete.php @@ -19,7 +19,8 @@ function tag_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function tag_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/Tag/Get.php b/civicrm/api/v3/examples/Tag/Get.php index 8860a11c72e9cd09380be3557a3af021e1cea8ff..a39d5c6a8e57ac4ec11c6fbb94963d4850eaad98 100644 --- a/civicrm/api/v3/examples/Tag/Get.php +++ b/civicrm/api/v3/examples/Tag/Get.php @@ -20,7 +20,8 @@ function tag_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Tag/GetFields.php b/civicrm/api/v3/examples/Tag/GetFields.php index eb38f1819234732bf5d354d753b2205c8f760e4c..c00491e909f6e7c57d99dc3feed04b7abcb69af7 100644 --- a/civicrm/api/v3/examples/Tag/GetFields.php +++ b/civicrm/api/v3/examples/Tag/GetFields.php @@ -21,7 +21,8 @@ function tag_getfields_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -41,13 +42,17 @@ function tag_getfields_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 10, + 'count' => 11, 'values' => array( 'id' => array( 'name' => 'id', 'type' => 1, 'title' => 'Tag ID', + 'description' => 'Tag ID', 'required' => TRUE, + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', 'api.aliases' => array( '0' => 'tag', ), @@ -56,23 +61,35 @@ function tag_getfields_expectedresult() { 'name' => 'name', 'type' => 2, 'title' => 'Tag Name', + 'description' => 'Name of Tag.', 'required' => TRUE, 'maxlength' => 64, 'size' => 30, + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', 'api.required' => 1, ), 'description' => array( 'name' => 'description', 'type' => 2, 'title' => 'Description', + 'description' => 'Optional verbose description of the tag.', 'maxlength' => 255, 'size' => 45, + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', ), 'parent_id' => array( 'name' => 'parent_id', 'type' => 1, 'title' => 'Parent Tag', + 'description' => 'Optional parent id for this tag.', 'default' => 'NULL', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', 'FKClassName' => 'CRM_Core_DAO_Tag', 'FKApiName' => 'Tag', ), @@ -80,17 +97,27 @@ function tag_getfields_expectedresult() { 'name' => 'is_selectable', 'type' => 16, 'title' => 'Display Tag?', + 'description' => 'Is this tag selectable / displayed', 'default' => '1', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', ), 'is_reserved' => array( 'name' => 'is_reserved', 'type' => 16, 'title' => 'Reserved', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', ), 'is_tagset' => array( 'name' => 'is_tagset', 'type' => 16, 'title' => 'Tagset', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', ), 'used_for' => array( 'name' => 'used_for', @@ -99,11 +126,17 @@ function tag_getfields_expectedresult() { 'maxlength' => 64, 'size' => 30, 'default' => 'NULL', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', 'html' => array( 'type' => 'Select', + 'maxlength' => 64, + 'size' => 30, ), 'pseudoconstant' => array( 'optionGroupName' => 'tag_used_for', + 'optionEditPath' => 'civicrm/admin/options/tag_used_for', ), 'api.default' => 'civicrm_contact', ), @@ -111,13 +144,33 @@ function tag_getfields_expectedresult() { 'name' => 'created_id', 'type' => 1, 'title' => 'Tag Created By', + 'description' => 'FK to civicrm_contact, who created this tag', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'FKApiName' => 'Contact', ), + 'color' => array( + 'name' => 'color', + 'type' => 2, + 'title' => 'Color', + 'description' => 'Hex color value e.g. #ffffff', + 'maxlength' => 255, + 'size' => 45, + 'default' => 'NULL', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', + ), 'created_date' => array( 'name' => 'created_date', 'type' => 12, 'title' => 'Tag Created Date', + 'description' => 'Date and time that tag was created.', + 'table_name' => 'civicrm_tag', + 'entity' => 'Tag', + 'bao' => 'CRM_Core_BAO_Tag', ), ), ); diff --git a/civicrm/api/v3/examples/Tag/GetList.php b/civicrm/api/v3/examples/Tag/GetList.php index 9dd6c6ebc83eff00cc36784199a53619c351e90a..08db458290490a953b1570e21c2ae0d21c37b00b 100644 --- a/civicrm/api/v3/examples/Tag/GetList.php +++ b/civicrm/api/v3/examples/Tag/GetList.php @@ -24,7 +24,8 @@ function tag_getlist_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Tag/GetReturnArray.php b/civicrm/api/v3/examples/Tag/GetReturnArray.php index e3cb5b396bc572afafc8d60b5845a892133ac5fe..ae5465dce79c7a9d6ae40436f7e234702dbe25a0 100644 --- a/civicrm/api/v3/examples/Tag/GetReturnArray.php +++ b/civicrm/api/v3/examples/Tag/GetReturnArray.php @@ -25,7 +25,8 @@ function tag_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFField/Create.php b/civicrm/api/v3/examples/UFField/Create.php index ec39ee0013833f21a10c5ba5d5be1f6cec1efdd0..6710ce7375c817db8e448c22937e58ea6947b69e 100644 --- a/civicrm/api/v3/examples/UFField/Create.php +++ b/civicrm/api/v3/examples/UFField/Create.php @@ -28,7 +28,8 @@ function uf_field_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFField/Delete.php b/civicrm/api/v3/examples/UFField/Delete.php index a766ac75845927c1a58e807ab67aef88c5ad7319..996cb148ee73721bfaee4292edc3155f43fc4ec4 100644 --- a/civicrm/api/v3/examples/UFField/Delete.php +++ b/civicrm/api/v3/examples/UFField/Delete.php @@ -19,7 +19,8 @@ function uf_field_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFField/Get.php b/civicrm/api/v3/examples/UFField/Get.php index 9c52c59d20418abb53adedf7cd4b6482b0c0aa72..c6c1a6b2df4494ca0ccf4d61d52965be106a1916 100644 --- a/civicrm/api/v3/examples/UFField/Get.php +++ b/civicrm/api/v3/examples/UFField/Get.php @@ -17,7 +17,8 @@ function uf_field_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFField/Replace.php b/civicrm/api/v3/examples/UFField/Replace.php index f94ad49347d9066536b138bbdc647b4c7b5ac5b6..992d678986a662dc0e71ea79779e3c2efb385fd6 100644 --- a/civicrm/api/v3/examples/UFField/Replace.php +++ b/civicrm/api/v3/examples/UFField/Replace.php @@ -53,7 +53,8 @@ function uf_field_replace_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFGroup/Create.php b/civicrm/api/v3/examples/UFGroup/Create.php index fdf7ada9352970353a5dab2f30ffa29e62dc2a8d..ade13f1fbe2cad305c994de0139787cd521303c5 100644 --- a/civicrm/api/v3/examples/UFGroup/Create.php +++ b/civicrm/api/v3/examples/UFGroup/Create.php @@ -38,7 +38,8 @@ function uf_group_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -81,7 +82,7 @@ function uf_group_create_expectedresult() { 'is_cms_user' => '1', 'notify' => 'admin@example.org', 'is_reserved' => '1', - 'name' => 'Test_Group_2', + 'name' => 'Test_Group', 'created_id' => '1', 'created_date' => '2013-07-28 08:49:19', 'is_proximity_search' => '', diff --git a/civicrm/api/v3/examples/UFGroup/Delete.php b/civicrm/api/v3/examples/UFGroup/Delete.php index c2be5ea33089e6c08deba871c5224951e41f4c0a..68855a931e51228f8d3b0c1d0c9048f52f0ad60d 100644 --- a/civicrm/api/v3/examples/UFGroup/Delete.php +++ b/civicrm/api/v3/examples/UFGroup/Delete.php @@ -19,7 +19,8 @@ function uf_group_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -40,7 +41,7 @@ function uf_group_delete_expectedresult() { 'is_error' => 0, 'version' => 3, 'count' => 1, - 'values' => TRUE, + 'values' => 1, ); return $expectedResult; diff --git a/civicrm/api/v3/examples/UFGroup/Get.php b/civicrm/api/v3/examples/UFGroup/Get.php index b35be5d2ba09cf178e61b28c018b766571a188df..1ce438b38b975e5e1c152002b3dda4566cd1d83a 100644 --- a/civicrm/api/v3/examples/UFGroup/Get.php +++ b/civicrm/api/v3/examples/UFGroup/Get.php @@ -19,7 +19,8 @@ function uf_group_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -61,7 +62,7 @@ function uf_group_get_expectedresult() { 'is_cms_user' => '1', 'notify' => 'admin@example.org', 'is_reserved' => '1', - 'name' => 'Test_Group_2', + 'name' => 'Test_Group', 'created_id' => '1', 'created_date' => '2013-07-28 08:49:19', 'is_proximity_search' => 0, diff --git a/civicrm/api/v3/examples/UFJoin/Create.php b/civicrm/api/v3/examples/UFJoin/Create.php index fa380d97d2c23f135424851bb4cae010a6750512..45eb69fec1c9109fd3802bdbc47ad9e4e919ce64 100644 --- a/civicrm/api/v3/examples/UFJoin/Create.php +++ b/civicrm/api/v3/examples/UFJoin/Create.php @@ -7,8 +7,8 @@ */ function uf_join_create_example() { $params = array( - 'module' => 'CiviContribute', - 'entity_table' => 'civicrm_contribution_page', + 'module' => 'CiviCampaign', + 'entity_table' => 'civicrm_survey', 'entity_id' => 1, 'weight' => 1, 'uf_group_id' => 11, @@ -25,7 +25,8 @@ function uf_join_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -51,8 +52,8 @@ function uf_join_create_expectedresult() { '0' => array( 'id' => '1', 'is_active' => '1', - 'module' => 'CiviContribute', - 'entity_table' => 'civicrm_contribution_page', + 'module' => 'CiviCampaign', + 'entity_table' => 'civicrm_survey', 'entity_id' => '1', 'weight' => '1', 'uf_group_id' => '11', @@ -66,7 +67,7 @@ function uf_join_create_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testCreateUFJoin" +* The test that created it is called "testCreateSurveyUFJoin" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/UFJoinTest.php * diff --git a/civicrm/api/v3/examples/UFJoin/Get.php b/civicrm/api/v3/examples/UFJoin/Get.php index 1328f59812e2d15d23ea3c298ab94bb55cdd9b4f..6f38609a02de252ffc443cf6090afb436d49a1fe 100644 --- a/civicrm/api/v3/examples/UFJoin/Get.php +++ b/civicrm/api/v3/examples/UFJoin/Get.php @@ -21,7 +21,8 @@ function uf_join_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/UFMatch/Get.php b/civicrm/api/v3/examples/UFMatch/Get.php index de24f6be46c28f60022ffa51fff79fc1a2ac452e..dddd476237eb2ca74af5badcd4bbf4ddc858d126 100644 --- a/civicrm/api/v3/examples/UFMatch/Get.php +++ b/civicrm/api/v3/examples/UFMatch/Get.php @@ -19,7 +19,8 @@ function uf_match_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Website/Create.php b/civicrm/api/v3/examples/Website/Create.php index 89a347ffbde261d88a6858f0036470b08806a85b..1e1d4e10fa0ab892c3d2d191674e96be335f2e98 100644 --- a/civicrm/api/v3/examples/Website/Create.php +++ b/civicrm/api/v3/examples/Website/Create.php @@ -21,7 +21,8 @@ function website_create_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Website/Delete.php b/civicrm/api/v3/examples/Website/Delete.php index fea28bf1645b24c59919101975abad2c7d4eddad..e40f33ac4ba072cfbd83b3482a926b7bf69c2c91 100644 --- a/civicrm/api/v3/examples/Website/Delete.php +++ b/civicrm/api/v3/examples/Website/Delete.php @@ -19,7 +19,8 @@ function website_delete_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Website/Get.php b/civicrm/api/v3/examples/Website/Get.php index 4b26815ce96b001f01cd97293fc288fa7a1fb2d0..75474912271286714ce1d566a0d13bdfda1e5462 100644 --- a/civicrm/api/v3/examples/Website/Get.php +++ b/civicrm/api/v3/examples/Website/Get.php @@ -21,7 +21,8 @@ function website_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); diff --git a/civicrm/api/v3/examples/Website/GetFields.php b/civicrm/api/v3/examples/Website/GetFields.php index 915c3c238aa6bd89a418c74c2b6cabf1e0a54aa1..1f163d8dc5a409c51f6306e37e72fd392773fa4d 100644 --- a/civicrm/api/v3/examples/Website/GetFields.php +++ b/civicrm/api/v3/examples/Website/GetFields.php @@ -19,7 +19,8 @@ function website_getfields_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -45,7 +46,11 @@ function website_getfields_expectedresult() { 'name' => 'id', 'type' => 1, 'title' => 'Website ID', + 'description' => 'Unique Website ID', 'required' => TRUE, + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'api.aliases' => array( '0' => 'website_id', ), @@ -54,6 +59,10 @@ function website_getfields_expectedresult() { 'name' => 'contact_id', 'type' => 1, 'title' => 'Contact', + 'description' => 'FK to Contact ID', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'FKApiName' => 'Contact', ), @@ -61,6 +70,7 @@ function website_getfields_expectedresult() { 'name' => 'url', 'type' => 2, 'title' => 'Website', + 'description' => 'Website', 'maxlength' => 128, 'size' => 30, 'import' => TRUE, @@ -68,19 +78,31 @@ function website_getfields_expectedresult() { 'headerPattern' => '/Website/i', 'dataPattern' => '/^[A-Za-z][0-9A-Za-z]{20,}$/', 'export' => TRUE, + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'html' => array( 'type' => 'Text', + 'maxlength' => 128, + 'size' => 30, ), ), 'website_type_id' => array( 'name' => 'website_type_id', 'type' => 1, 'title' => 'Website Type', + 'description' => 'Which Website type does this website belong to.', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'html' => array( 'type' => 'Select', + 'size' => 6, + 'maxlength' => 14, ), 'pseudoconstant' => array( 'optionGroupName' => 'website_type', + 'optionEditPath' => 'civicrm/admin/options/website_type', ), ), ), diff --git a/civicrm/api/v3/examples/Website/GetWithMetadata.php b/civicrm/api/v3/examples/Website/GetWithMetadata.php index db2e42874cdfcf55e3aab181c335c2111bedfa18..24c4467ddd2a3dcdf5be2222243343d775730cfa 100644 --- a/civicrm/api/v3/examples/Website/GetWithMetadata.php +++ b/civicrm/api/v3/examples/Website/GetWithMetadata.php @@ -25,7 +25,8 @@ function website_get_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -53,7 +54,11 @@ function website_get_expectedresult() { 'name' => 'id', 'type' => '1', 'title' => 'Website ID', + 'description' => 'Unique Website ID', 'required' => '1', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'api.aliases' => array( '0' => 'website_id', ), @@ -62,6 +67,10 @@ function website_get_expectedresult() { 'name' => 'contact_id', 'type' => '1', 'title' => 'Contact', + 'description' => 'FK to Contact ID', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'FKClassName' => 'CRM_Contact_DAO_Contact', 'FKApiName' => 'Contact', ), @@ -69,6 +78,7 @@ function website_get_expectedresult() { 'name' => 'url', 'type' => '2', 'title' => 'Website', + 'description' => 'Website', 'maxlength' => '128', 'size' => '30', 'import' => '1', @@ -76,19 +86,31 @@ function website_get_expectedresult() { 'headerPattern' => '/Website/i', 'dataPattern' => '/^[A-Za-z][0-9A-Za-z]{20,}$/', 'export' => '1', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'html' => array( 'type' => 'Text', + 'maxlength' => '128', + 'size' => '30', ), ), 'website_type_id' => array( 'name' => 'website_type_id', 'type' => '1', 'title' => 'Website Type', + 'description' => 'Which Website type does this website belong to.', + 'table_name' => 'civicrm_website', + 'entity' => 'Website', + 'bao' => 'CRM_Core_BAO_Website', 'html' => array( 'type' => 'Select', + 'size' => '6', + 'maxlength' => '14', ), 'pseudoconstant' => array( 'optionGroupName' => 'website_type', + 'optionEditPath' => 'civicrm/admin/options/website_type', ), ), ), diff --git a/civicrm/api/v3/utils.php b/civicrm/api/v3/utils.php index 741ab966cdcadd51aa2af73b691e71a47ed83a30..1e5400b4197b7c0c6266c6fa765e0247afd45799 100644 --- a/civicrm/api/v3/utils.php +++ b/civicrm/api/v3/utils.php @@ -1887,8 +1887,10 @@ function _civicrm_api_get_fields($entity, $unique = FALSE, &$params = array()) { $d = new $dao(); $fields = $d->fields(); - // Set html attributes for text fields foreach ($fields as $name => &$field) { + // Denote as core field + $field['is_core_field'] = TRUE; + // Set html attributes for text fields if (isset($field['html'])) { $field['html'] += (array) $d::makeAttribute($field); } @@ -2062,7 +2064,7 @@ function _civicrm_api3_swap_out_aliases(&$apiRequest, $fields) { * * @throws API_Exception */ -function _civicrm_api3_validate_integer(&$params, &$fieldName, &$fieldInfo, $entity) { +function _civicrm_api3_validate_integer(&$params, $fieldName, &$fieldInfo, $entity) { list($fieldValue, $op) = _civicrm_api3_field_value_check($params, $fieldName); if (strpos($op, 'NULL') !== FALSE || strpos($op, 'EMPTY') !== FALSE) { return; diff --git a/civicrm/bower.json b/civicrm/bower.json index 7db9f6bb6ea907aad547b45c45f463c29fea2c02..d5cda3c0d015cc0b757e6cbbda0db5aa09e389d1 100644 --- a/civicrm/bower.json +++ b/civicrm/bower.json @@ -22,6 +22,7 @@ "select2": "colemanw/select2#stable/3.5", "jquery-validation": "~1.13", "datatables": "~1.10", + "jstree": "~3", "ckeditor": "~4.5", "font-awesome": "~4", "angular-sanitize": "~1.3.15" diff --git a/civicrm/bower_components/jstree/.bower.json b/civicrm/bower_components/jstree/.bower.json new file mode 100644 index 0000000000000000000000000000000000000000..fa438410373f3134d82a85648a2f9ebef2e9879a --- /dev/null +++ b/civicrm/bower_components/jstree/.bower.json @@ -0,0 +1,42 @@ +{ + "name": "jstree", + "version": "3.3.3", + "main": [ + "./dist/jstree.js", + "./dist/themes/default/style.css" + ], + "ignore": [ + "**/.*", + "docs", + "demo", + "libs", + "node_modules", + "test", + "libs", + "jstree.jquery.json", + "gruntfile.js", + "package.json", + "bower.json", + "component.json", + "LICENCE-MIT", + "README.md" + ], + "dependencies": { + "jquery": ">=1.9.1" + }, + "keywords": [ + "ui", + "tree", + "jstree" + ], + "homepage": "https://github.com/vakata/jstree", + "_release": "3.3.3", + "_resolution": { + "type": "version", + "tag": "3.3.3", + "commit": "9770c6711f0a155ec494f635aaf0add9b3cfb45c" + }, + "_source": "https://github.com/vakata/jstree.git", + "_target": "~3", + "_originalSource": "jstree" +} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/LICENSE-MIT b/civicrm/bower_components/jstree/LICENSE-MIT new file mode 100644 index 0000000000000000000000000000000000000000..9c90a3d3980732db195477c7e405ebbbac55b14a --- /dev/null +++ b/civicrm/bower_components/jstree/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2014 Ivan Bozhanov + +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. diff --git a/civicrm/bower_components/jstree/bower.json b/civicrm/bower_components/jstree/bower.json new file mode 100644 index 0000000000000000000000000000000000000000..535b66c1514535ddbb8e8043eba48def3a36ca24 --- /dev/null +++ b/civicrm/bower_components/jstree/bower.json @@ -0,0 +1,32 @@ +{ + "name": "jstree", + "version": "3.3.3", + "main" : [ + "./dist/jstree.js", + "./dist/themes/default/style.css" + ], + "ignore": [ + "**/.*", + "docs", + "demo", + "libs", + "node_modules", + "test", + "libs", + "jstree.jquery.json", + "gruntfile.js", + "package.json", + "bower.json", + "component.json", + "LICENCE-MIT", + "README.md" + ], + "dependencies": { + "jquery": ">=1.9.1" + }, + "keywords": [ + "ui", + "tree", + "jstree" + ] +} diff --git a/civicrm/bower_components/jstree/composer.json b/civicrm/bower_components/jstree/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..282b768a688f615035f4eeab8e0465ed4a972ac5 --- /dev/null +++ b/civicrm/bower_components/jstree/composer.json @@ -0,0 +1,46 @@ +{ + "name": "vakata/jstree", + "description": "jsTree is jquery plugin, that provides interactive trees.", + "type": "component", + "homepage": "http://jstree.com", + "license": "MIT", + "support": { + "issues": "https://github.com/vakata/jstree/issues", + "forum": "https://groups.google.com/forum/#!forum/jstree", + "source": "https://github.com/vakata/jstree" + }, + "authors": [ + { + "name": "Ivan Bozhanov", + "email": "jstree@jstree.com" + } + ], + "require": { + "components/jquery": ">=1.9.1" + }, + "suggest": { + "robloach/component-installer": "Allows installation of Components via Composer" + }, + "extra": { + "component": { + "scripts": [ + "dist/jstree.js" + ], + "styles": [ + "dist/themes/default/style.css" + ], + "images": [ + "dist/themes/default/32px.png", + "dist/themes/default/40px.png", + "dist/themes/default/throbber.gif" + ], + "files": [ + "dist/jstree.min.js", + "dist/themes/default/style.min.css", + "dist/themes/default/32px.png", + "dist/themes/default/40px.png", + "dist/themes/default/throbber.gif" + ] + } + } +} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/dist/jstree.js b/civicrm/bower_components/jstree/dist/jstree.js new file mode 100644 index 0000000000000000000000000000000000000000..b6509d4671feec51dab4d3dc00ce8c94a2f7b428 --- /dev/null +++ b/civicrm/bower_components/jstree/dist/jstree.js @@ -0,0 +1,8305 @@ +/*globals jQuery, define, module, exports, require, window, document, postMessage */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else if(typeof module !== 'undefined' && module.exports) { + module.exports = factory(require('jquery')); + } + else { + factory(jQuery); + } +}(function ($, undefined) { + "use strict"; +/*! + * jsTree 3.3.3 + * http://jstree.com/ + * + * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com) + * + * Licensed same as jquery - under the terms of the MIT License + * http://www.opensource.org/licenses/mit-license.php + */ +/*! + * if using jslint please allow for the jQuery global and use following options: + * jslint: loopfunc: true, browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true + */ +/*jshint -W083 */ + + // prevent another load? maybe there is a better way? + if($.jstree) { + return; + } + + /** + * ### jsTree core functionality + */ + + // internal variables + var instance_counter = 0, + ccp_node = false, + ccp_mode = false, + ccp_inst = false, + themes_loaded = [], + src = $('script:last').attr('src'), + document = window.document; // local variable is always faster to access then a global + + /** + * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances. + * @name $.jstree + */ + $.jstree = { + /** + * specifies the jstree version in use + * @name $.jstree.version + */ + version : '3.3.3', + /** + * holds all the default options used when creating new instances + * @name $.jstree.defaults + */ + defaults : { + /** + * configure which plugins will be active on an instance. Should be an array of strings, where each element is a plugin name. The default is `[]` + * @name $.jstree.defaults.plugins + */ + plugins : [] + }, + /** + * stores all loaded jstree plugins (used internally) + * @name $.jstree.plugins + */ + plugins : {}, + path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '', + idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g, + root : '#' + }; + + /** + * creates a jstree instance + * @name $.jstree.create(el [, options]) + * @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector + * @param {Object} options options for this instance (extends `$.jstree.defaults`) + * @return {jsTree} the new instance + */ + $.jstree.create = function (el, options) { + var tmp = new $.jstree.core(++instance_counter), + opt = options; + options = $.extend(true, {}, $.jstree.defaults, options); + if(opt && opt.plugins) { + options.plugins = opt.plugins; + } + $.each(options.plugins, function (i, k) { + if(i !== 'core') { + tmp = tmp.plugin(k, options[k]); + } + }); + $(el).data('jstree', tmp); + tmp.init(el, options); + return tmp; + }; + /** + * remove all traces of jstree from the DOM and destroy all instances + * @name $.jstree.destroy() + */ + $.jstree.destroy = function () { + $('.jstree:jstree').jstree('destroy'); + $(document).off('.jstree'); + }; + /** + * the jstree class constructor, used only internally + * @private + * @name $.jstree.core(id) + * @param {Number} id this instance's index + */ + $.jstree.core = function (id) { + this._id = id; + this._cnt = 0; + this._wrk = null; + this._data = { + core : { + themes : { + name : false, + dots : false, + icons : false, + ellipsis : false + }, + selected : [], + last_error : {}, + working : false, + worker_queue : [], + focused : null + } + }; + }; + /** + * get a reference to an existing instance + * + * __Examples__ + * + * // provided a container with an ID of "tree", and a nested node with an ID of "branch" + * // all of there will return the same instance + * $.jstree.reference('tree'); + * $.jstree.reference('#tree'); + * $.jstree.reference($('#tree')); + * $.jstree.reference(document.getElementByID('tree')); + * $.jstree.reference('branch'); + * $.jstree.reference('#branch'); + * $.jstree.reference($('#branch')); + * $.jstree.reference(document.getElementByID('branch')); + * + * @name $.jstree.reference(needle) + * @param {DOMElement|jQuery|String} needle + * @return {jsTree|null} the instance or `null` if not found + */ + $.jstree.reference = function (needle) { + var tmp = null, + obj = null; + if(needle && needle.id && (!needle.tagName || !needle.nodeType)) { needle = needle.id; } + + if(!obj || !obj.length) { + try { obj = $(needle); } catch (ignore) { } + } + if(!obj || !obj.length) { + try { obj = $('#' + needle.replace($.jstree.idregex,'\\$&')); } catch (ignore) { } + } + if(obj && obj.length && (obj = obj.closest('.jstree')).length && (obj = obj.data('jstree'))) { + tmp = obj; + } + else { + $('.jstree').each(function () { + var inst = $(this).data('jstree'); + if(inst && inst._model.data[needle]) { + tmp = inst; + return false; + } + }); + } + return tmp; + }; + /** + * Create an instance, get an instance or invoke a command on a instance. + * + * If there is no instance associated with the current node a new one is created and `arg` is used to extend `$.jstree.defaults` for this new instance. There would be no return value (chaining is not broken). + * + * If there is an existing instance and `arg` is a string the command specified by `arg` is executed on the instance, with any additional arguments passed to the function. If the function returns a value it will be returned (chaining could break depending on function). + * + * If there is an existing instance and `arg` is not a string the instance itself is returned (similar to `$.jstree.reference`). + * + * In any other case - nothing is returned and chaining is not broken. + * + * __Examples__ + * + * $('#tree1').jstree(); // creates an instance + * $('#tree2').jstree({ plugins : [] }); // create an instance with some options + * $('#tree1').jstree('open_node', '#branch_1'); // call a method on an existing instance, passing additional arguments + * $('#tree2').jstree(); // get an existing instance (or create an instance) + * $('#tree2').jstree(true); // get an existing instance (will not create new instance) + * $('#branch_1').jstree().select_node('#branch_1'); // get an instance (using a nested element and call a method) + * + * @name $().jstree([arg]) + * @param {String|Object} arg + * @return {Mixed} + */ + $.fn.jstree = function (arg) { + // check for string argument + var is_method = (typeof arg === 'string'), + args = Array.prototype.slice.call(arguments, 1), + result = null; + if(arg === true && !this.length) { return false; } + this.each(function () { + // get the instance (if there is one) and method (if it exists) + var instance = $.jstree.reference(this), + method = is_method && instance ? instance[arg] : null; + // if calling a method, and method is available - execute on the instance + result = is_method && method ? + method.apply(instance, args) : + null; + // if there is no instance and no method is being called - create one + if(!instance && !is_method && (arg === undefined || $.isPlainObject(arg))) { + $.jstree.create(this, arg); + } + // if there is an instance and no method is called - return the instance + if( (instance && !is_method) || arg === true ) { + result = instance || false; + } + // if there was a method call which returned a result - break and return the value + if(result !== null && result !== undefined) { + return false; + } + }); + // if there was a method call with a valid return value - return that, otherwise continue the chain + return result !== null && result !== undefined ? + result : this; + }; + /** + * used to find elements containing an instance + * + * __Examples__ + * + * $('div:jstree').each(function () { + * $(this).jstree('destroy'); + * }); + * + * @name $(':jstree') + * @return {jQuery} + */ + $.expr.pseudos.jstree = $.expr.createPseudo(function(search) { + return function(a) { + return $(a).hasClass('jstree') && + $(a).data('jstree') !== undefined; + }; + }); + + /** + * stores all defaults for the core + * @name $.jstree.defaults.core + */ + $.jstree.defaults.core = { + /** + * data configuration + * + * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items). + * + * You can also pass in a HTML string or a JSON array here. + * + * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree. + * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used. + * + * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result. + * + * __Examples__ + * + * // AJAX + * $('#tree').jstree({ + * 'core' : { + * 'data' : { + * 'url' : '/get/children/', + * 'data' : function (node) { + * return { 'id' : node.id }; + * } + * } + * }); + * + * // direct data + * $('#tree').jstree({ + * 'core' : { + * 'data' : [ + * 'Simple root node', + * { + * 'id' : 'node_2', + * 'text' : 'Root node with options', + * 'state' : { 'opened' : true, 'selected' : true }, + * 'children' : [ { 'text' : 'Child 1' }, 'Child 2'] + * } + * ] + * } + * }); + * + * // function + * $('#tree').jstree({ + * 'core' : { + * 'data' : function (obj, callback) { + * callback.call(this, ['Root 1', 'Root 2']); + * } + * }); + * + * @name $.jstree.defaults.core.data + */ + data : false, + /** + * configure the various strings used throughout the tree + * + * You can use an object where the key is the string you need to replace and the value is your replacement. + * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement. + * If left as `false` no replacement is made. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'strings' : { + * 'Loading ...' : 'Please wait ...' + * } + * } + * }); + * + * @name $.jstree.defaults.core.strings + */ + strings : false, + /** + * determines what happens when a user tries to modify the structure of the tree + * If left as `false` all operations like create, rename, delete, move or copy are prevented. + * You can set this to `true` to allow all interactions or use a function to have better control. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'check_callback' : function (operation, node, node_parent, node_position, more) { + * // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node' + * // in case of 'rename_node' node_position is filled with the new node name + * return operation === 'rename_node' ? true : false; + * } + * } + * }); + * + * @name $.jstree.defaults.core.check_callback + */ + check_callback : false, + /** + * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc) + * @name $.jstree.defaults.core.error + */ + error : $.noop, + /** + * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`) + * @name $.jstree.defaults.core.animation + */ + animation : 200, + /** + * a boolean indicating if multiple nodes can be selected + * @name $.jstree.defaults.core.multiple + */ + multiple : true, + /** + * theme configuration object + * @name $.jstree.defaults.core.themes + */ + themes : { + /** + * the name of the theme to use (if left as `false` the default theme is used) + * @name $.jstree.defaults.core.themes.name + */ + name : false, + /** + * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme. + * @name $.jstree.defaults.core.themes.url + */ + url : false, + /** + * the location of all jstree themes - only used if `url` is set to `true` + * @name $.jstree.defaults.core.themes.dir + */ + dir : false, + /** + * a boolean indicating if connecting dots are shown + * @name $.jstree.defaults.core.themes.dots + */ + dots : true, + /** + * a boolean indicating if node icons are shown + * @name $.jstree.defaults.core.themes.icons + */ + icons : true, + /** + * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container + * @name $.jstree.defaults.core.themes.ellipsis + */ + ellipsis : false, + /** + * a boolean indicating if the tree background is striped + * @name $.jstree.defaults.core.themes.stripes + */ + stripes : false, + /** + * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants) + * @name $.jstree.defaults.core.themes.variant + */ + variant : false, + /** + * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `false`. + * @name $.jstree.defaults.core.themes.responsive + */ + responsive : false + }, + /** + * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user) + * @name $.jstree.defaults.core.expand_selected_onload + */ + expand_selected_onload : true, + /** + * if left as `true` web workers will be used to parse incoming JSON data where possible, so that the UI will not be blocked by large requests. Workers are however about 30% slower. Defaults to `true` + * @name $.jstree.defaults.core.worker + */ + worker : true, + /** + * Force node text to plain text (and escape HTML). Defaults to `false` + * @name $.jstree.defaults.core.force_text + */ + force_text : false, + /** + * Should the node should be toggled if the text is double clicked . Defaults to `true` + * @name $.jstree.defaults.core.dblclick_toggle + */ + dblclick_toggle : true + }; + $.jstree.core.prototype = { + /** + * used to decorate an instance with a plugin. Used internally. + * @private + * @name plugin(deco [, opts]) + * @param {String} deco the plugin to decorate with + * @param {Object} opts options for the plugin + * @return {jsTree} + */ + plugin : function (deco, opts) { + var Child = $.jstree.plugins[deco]; + if(Child) { + this._data[deco] = {}; + Child.prototype = this; + return new Child(opts, this); + } + return this; + }, + /** + * initialize the instance. Used internally. + * @private + * @name init(el, optons) + * @param {DOMElement|jQuery|String} el the element we are transforming + * @param {Object} options options for this instance + * @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree + */ + init : function (el, options) { + this._model = { + data : {}, + changed : [], + force_full_redraw : false, + redraw_timeout : false, + default_state : { + loaded : true, + opened : false, + selected : false, + disabled : false + } + }; + this._model.data[$.jstree.root] = { + id : $.jstree.root, + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + }; + + this.element = $(el).addClass('jstree jstree-' + this._id); + this.settings = options; + + this._data.core.ready = false; + this._data.core.loaded = false; + this._data.core.rtl = (this.element.css("direction") === "rtl"); + this.element[this._data.core.rtl ? 'addClass' : 'removeClass']("jstree-rtl"); + this.element.attr('role','tree'); + if(this.settings.core.multiple) { + this.element.attr('aria-multiselectable', true); + } + if(!this.element.attr('tabindex')) { + this.element.attr('tabindex','0'); + } + + this.bind(); + /** + * triggered after all events are bound + * @event + * @name init.jstree + */ + this.trigger("init"); + + this._data.core.original_container_html = this.element.find(" > ul > li").clone(true); + this._data.core.original_container_html + .find("li").addBack() + .contents().filter(function() { + return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue)); + }) + .remove(); + this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>"); + this.element.attr('aria-activedescendant','j' + this._id + '_loading'); + this._data.core.li_height = this.get_container_ul().children("li").first().height() || 24; + this._data.core.node = this._create_prototype_node(); + /** + * triggered after the loading text is shown and before loading starts + * @event + * @name loading.jstree + */ + this.trigger("loading"); + this.load_node($.jstree.root); + }, + /** + * destroy an instance + * @name destroy() + * @param {Boolean} keep_html if not set to `true` the container will be emptied, otherwise the current DOM elements will be kept intact + */ + destroy : function (keep_html) { + if(this._wrk) { + try { + window.URL.revokeObjectURL(this._wrk); + this._wrk = null; + } + catch (ignore) { } + } + if(!keep_html) { this.element.empty(); } + this.teardown(); + }, + /** + * Create prototype node + */ + _create_prototype_node : function () { + var _node = document.createElement('LI'), _temp1, _temp2; + _node.setAttribute('role', 'treeitem'); + _temp1 = document.createElement('I'); + _temp1.className = 'jstree-icon jstree-ocl'; + _temp1.setAttribute('role', 'presentation'); + _node.appendChild(_temp1); + _temp1 = document.createElement('A'); + _temp1.className = 'jstree-anchor'; + _temp1.setAttribute('href','#'); + _temp1.setAttribute('tabindex','-1'); + _temp2 = document.createElement('I'); + _temp2.className = 'jstree-icon jstree-themeicon'; + _temp2.setAttribute('role', 'presentation'); + _temp1.appendChild(_temp2); + _node.appendChild(_temp1); + _temp1 = _temp2 = null; + + return _node; + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name teardown() + */ + teardown : function () { + this.unbind(); + this.element + .removeClass('jstree') + .removeData('jstree') + .find("[class^='jstree']") + .addBack() + .attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); }); + this.element = null; + }, + /** + * bind all events. Used internally. + * @private + * @name bind() + */ + bind : function () { + var word = '', + tout = null, + was_click = 0; + this.element + .on("dblclick.jstree", function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(document.selection && document.selection.empty) { + document.selection.empty(); + } + else { + if(window.getSelection) { + var sel = window.getSelection(); + try { + sel.removeAllRanges(); + sel.collapse(); + } catch (ignore) { } + } + } + }) + .on("mousedown.jstree", $.proxy(function (e) { + if(e.target === this.element[0]) { + e.preventDefault(); // prevent losing focus when clicking scroll arrows (FF, Chrome) + was_click = +(new Date()); // ie does not allow to prevent losing focus + } + }, this)) + .on("mousedown.jstree", ".jstree-ocl", function (e) { + e.preventDefault(); // prevent any node inside from losing focus when clicking the open/close icon + }) + .on("click.jstree", ".jstree-ocl", $.proxy(function (e) { + this.toggle_node(e.target); + }, this)) + .on("dblclick.jstree", ".jstree-anchor", $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(this.settings.core.dblclick_toggle) { + this.toggle_node(e.target); + } + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + e.preventDefault(); + if(e.currentTarget !== document.activeElement) { $(e.currentTarget).focus(); } + this.activate_node(e.currentTarget, e); + }, this)) + .on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(e.which !== 32 && e.which !== 13 && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) { return true; } + var o = null; + if(this._data.core.rtl) { + if(e.which === 37) { e.which = 39; } + else if(e.which === 39) { e.which = 37; } + } + switch(e.which) { + case 32: // aria defines space only with Ctrl + if(e.ctrlKey) { + e.type = "click"; + $(e.currentTarget).trigger(e); + } + break; + case 13: // enter + e.type = "click"; + $(e.currentTarget).trigger(e); + break; + case 37: // left + e.preventDefault(); + if(this.is_open(e.currentTarget)) { + this.close_node(e.currentTarget); + } + else { + o = this.get_parent(e.currentTarget); + if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); } + } + break; + case 38: // up + e.preventDefault(); + o = this.get_prev_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + case 39: // right + e.preventDefault(); + if(this.is_closed(e.currentTarget)) { + this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); }); + } + else if (this.is_open(e.currentTarget)) { + o = this.get_node(e.currentTarget, true).children('.jstree-children')[0]; + if(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); } + } + break; + case 40: // down + e.preventDefault(); + o = this.get_next_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + case 106: // aria defines * on numpad as open_all - not very common + this.open_all(); + break; + case 36: // home + e.preventDefault(); + o = this._firstChild(this.get_container_ul()[0]); + if(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); } + break; + case 35: // end + e.preventDefault(); + this.element.find('.jstree-anchor').filter(':visible').last().focus(); + break; + case 113: // f2 - safe to include - if check_callback is false it will fail + e.preventDefault(); + this.edit(e.currentTarget); + break; + default: + break; + /*! + // delete + case 46: + e.preventDefault(); + o = this.get_node(e.currentTarget); + if(o && o.id && o.id !== $.jstree.root) { + o = this.is_selected(o) ? this.get_selected() : o; + this.delete_node(o); + } + break; + + */ + } + }, this)) + .on("load_node.jstree", $.proxy(function (e, data) { + if(data.status) { + if(data.node.id === $.jstree.root && !this._data.core.loaded) { + this._data.core.loaded = true; + if(this._firstChild(this.get_container_ul()[0])) { + this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id); + } + /** + * triggered after the root node is loaded for the first time + * @event + * @name loaded.jstree + */ + this.trigger("loaded"); + } + if(!this._data.core.ready) { + setTimeout($.proxy(function() { + if(this.element && !this.get_container_ul().find('.jstree-loading').length) { + this._data.core.ready = true; + if(this._data.core.selected.length) { + if(this.settings.core.expand_selected_onload) { + var tmp = [], i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + tmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents); + } + tmp = $.vakata.array_unique(tmp); + for(i = 0, j = tmp.length; i < j; i++) { + this.open_node(tmp[i], false, 0); + } + } + this.trigger('changed', { 'action' : 'ready', 'selected' : this._data.core.selected }); + } + /** + * triggered after all nodes are finished loading + * @event + * @name ready.jstree + */ + this.trigger("ready"); + } + }, this), 0); + } + } + }, this)) + // quick searching when the tree is focused + .on('keypress.jstree', $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(tout) { clearTimeout(tout); } + tout = setTimeout(function () { + word = ''; + }, 500); + + var chr = String.fromCharCode(e.which).toLowerCase(), + col = this.element.find('.jstree-anchor').filter(':visible'), + ind = col.index(document.activeElement) || 0, + end = false; + word += chr; + + // match for whole word from current node down (including the current node) + if(word.length > 1) { + col.slice(ind).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().indexOf(word) === 0) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + + // match for whole word from the beginning of the tree + col.slice(0, ind).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().indexOf(word) === 0) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + } + // list nodes that start with that letter (only if word consists of a single char) + if(new RegExp('^' + chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) { + // search for the next node starting with that letter + col.slice(ind + 1).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().charAt(0) === chr) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + + // search from the beginning + col.slice(0, ind + 1).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().charAt(0) === chr) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + } + }, this)) + // THEME RELATED + .on("init.jstree", $.proxy(function () { + var s = this.settings.core.themes; + this._data.core.themes.dots = s.dots; + this._data.core.themes.stripes = s.stripes; + this._data.core.themes.icons = s.icons; + this._data.core.themes.ellipsis = s.ellipsis; + this.set_theme(s.name || "default", s.url); + this.set_theme_variant(s.variant); + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ](); + this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ](); + this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ](); + this[ this._data.core.themes.ellipsis ? "show_ellipsis" : "hide_ellipsis" ](); + }, this)) + .on('blur.jstree', '.jstree-anchor', $.proxy(function (e) { + this._data.core.focused = null; + $(e.currentTarget).filter('.jstree-hovered').mouseleave(); + this.element.attr('tabindex', '0'); + }, this)) + .on('focus.jstree', '.jstree-anchor', $.proxy(function (e) { + var tmp = this.get_node(e.currentTarget); + if(tmp && tmp.id) { + this._data.core.focused = tmp.id; + } + this.element.find('.jstree-hovered').not(e.currentTarget).mouseleave(); + $(e.currentTarget).mouseenter(); + this.element.attr('tabindex', '-1'); + }, this)) + .on('focus.jstree', $.proxy(function () { + if(+(new Date()) - was_click > 500 && !this._data.core.focused) { + was_click = 0; + var act = this.get_node(this.element.attr('aria-activedescendant'), true); + if(act) { + act.find('> .jstree-anchor').focus(); + } + } + }, this)) + .on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) { + this.hover_node(e.currentTarget); + }, this)) + .on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name unbind() + */ + unbind : function () { + this.element.off('.jstree'); + $(document).off('.jstree-' + this._id); + }, + /** + * trigger an event. Used internally. + * @private + * @name trigger(ev [, data]) + * @param {String} ev the name of the event to trigger + * @param {Object} data additional data to pass with the event + */ + trigger : function (ev, data) { + if(!data) { + data = {}; + } + data.instance = this; + this.element.triggerHandler(ev.replace('.jstree','') + '.jstree', data); + }, + /** + * returns the jQuery extended instance container + * @name get_container() + * @return {jQuery} + */ + get_container : function () { + return this.element; + }, + /** + * returns the jQuery extended main UL node inside the instance container. Used internally. + * @private + * @name get_container_ul() + * @return {jQuery} + */ + get_container_ul : function () { + return this.element.children(".jstree-children").first(); + }, + /** + * gets string replacements (localization). Used internally. + * @private + * @name get_string(key) + * @param {String} key + * @return {String} + */ + get_string : function (key) { + var a = this.settings.core.strings; + if($.isFunction(a)) { return a.call(this, key); } + if(a && a[key]) { return a[key]; } + return key; + }, + /** + * gets the first child of a DOM node. Used internally. + * @private + * @name _firstChild(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _firstChild : function (dom) { + dom = dom ? dom.firstChild : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the next sibling of a DOM node. Used internally. + * @private + * @name _nextSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _nextSibling : function (dom) { + dom = dom ? dom.nextSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the previous sibling of a DOM node. Used internally. + * @private + * @name _previousSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _previousSibling : function (dom) { + dom = dom ? dom.previousSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.previousSibling; + } + return dom; + }, + /** + * get the JSON representation of a node (or the actual jQuery extended DOM node) by using any input (child DOM element, ID string, selector, etc) + * @name get_node(obj [, as_dom]) + * @param {mixed} obj + * @param {Boolean} as_dom + * @return {Object|jQuery} + */ + get_node : function (obj, as_dom) { + if(obj && obj.id) { + obj = obj.id; + } + var dom; + try { + if(this._model.data[obj]) { + obj = this._model.data[obj]; + } + else if(typeof obj === "string" && this._model.data[obj.replace(/^#/, '')]) { + obj = this._model.data[obj.replace(/^#/, '')]; + } + else if(typeof obj === "string" && (dom = $('#' + obj.replace($.jstree.idregex,'\\$&'), this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) { + obj = this._model.data[dom.closest('.jstree-node').attr('id')]; + } + else if((dom = $(obj, this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) { + obj = this._model.data[dom.closest('.jstree-node').attr('id')]; + } + else if((dom = $(obj, this.element)).length && dom.hasClass('jstree')) { + obj = this._model.data[$.jstree.root]; + } + else { + return false; + } + + if(as_dom) { + obj = obj.id === $.jstree.root ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element); + } + return obj; + } catch (ex) { return false; } + }, + /** + * get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array) + * @name get_path(obj [, glue, ids]) + * @param {mixed} obj the node + * @param {String} glue if you want the path as a string - pass the glue here (for example '/'), if a falsy value is supplied here, an array is returned + * @param {Boolean} ids if set to true build the path using ID, otherwise node text is used + * @return {mixed} + */ + get_path : function (obj, glue, ids) { + obj = obj.parents ? obj : this.get_node(obj); + if(!obj || obj.id === $.jstree.root || !obj.parents) { + return false; + } + var i, j, p = []; + p.push(ids ? obj.id : obj.text); + for(i = 0, j = obj.parents.length; i < j; i++) { + p.push(ids ? obj.parents[i] : this.get_text(obj.parents[i])); + } + p = p.reverse().slice(1); + return glue ? p.join(glue) : p; + }, + /** + * get the next visible node that is below the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_next_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_next_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this._firstChild(this.get_container_ul()[0]); + while (tmp && tmp.offsetHeight === 0) { + tmp = this._nextSibling(tmp); + } + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = obj[0]; + do { + tmp = this._nextSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + return tmp ? $(tmp) : false; + } + if(obj.hasClass("jstree-open")) { + tmp = this._firstChild(obj.children('.jstree-children')[0]); + while (tmp && tmp.offsetHeight === 0) { + tmp = this._nextSibling(tmp); + } + if(tmp !== null) { + return $(tmp); + } + } + tmp = obj[0]; + do { + tmp = this._nextSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + if(tmp !== null) { + return $(tmp); + } + return obj.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first(); + }, + /** + * get the previous visible node that is above the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_prev_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_prev_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this.get_container_ul()[0].lastChild; + while (tmp && tmp.offsetHeight === 0) { + tmp = this._previousSibling(tmp); + } + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = obj[0]; + do { + tmp = this._previousSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + return tmp ? $(tmp) : false; + } + tmp = obj[0]; + do { + tmp = this._previousSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + if(tmp !== null) { + obj = $(tmp); + while(obj.hasClass("jstree-open")) { + obj = obj.children(".jstree-children").first().children(".jstree-node:visible:last"); + } + return obj; + } + tmp = obj[0].parentNode.parentNode; + return tmp && tmp.className && tmp.className.indexOf('jstree-node') !== -1 ? $(tmp) : false; + }, + /** + * get the parent ID of a node + * @name get_parent(obj) + * @param {mixed} obj + * @return {String} + */ + get_parent : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + return obj.parent; + }, + /** + * get a jQuery collection of all the children of a node (node must be rendered) + * @name get_children_dom(obj) + * @param {mixed} obj + * @return {jQuery} + */ + get_children_dom : function (obj) { + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + return this.get_container_ul().children(".jstree-node"); + } + if(!obj || !obj.length) { + return false; + } + return obj.children(".jstree-children").children(".jstree-node"); + }, + /** + * checks if a node has children + * @name is_parent(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_parent : function (obj) { + obj = this.get_node(obj); + return obj && (obj.state.loaded === false || obj.children.length > 0); + }, + /** + * checks if a node is loaded (its children are available) + * @name is_loaded(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loaded : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.loaded; + }, + /** + * check if a node is currently loading (fetching children) + * @name is_loading(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loading : function (obj) { + obj = this.get_node(obj); + return obj && obj.state && obj.state.loading; + }, + /** + * check if a node is opened + * @name is_open(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_open : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.opened; + }, + /** + * check if a node is in a closed state + * @name is_closed(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_closed : function (obj) { + obj = this.get_node(obj); + return obj && this.is_parent(obj) && !obj.state.opened; + }, + /** + * check if a node has no children + * @name is_leaf(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_leaf : function (obj) { + return !this.is_parent(obj); + }, + /** + * loads a node (fetches its children using the `core.data` setting). Multiple nodes can be passed to by using an array. + * @name load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives two arguments - the node and a boolean status + * @return {Boolean} + * @trigger load_node.jstree + */ + load_node : function (obj, callback) { + var k, l, i, j, c; + if($.isArray(obj)) { + this._load_nodes(obj.slice(), callback); + return true; + } + obj = this.get_node(obj); + if(!obj) { + if(callback) { callback.call(this, obj, false); } + return false; + } + // if(obj.state.loading) { } // the node is already loading - just wait for it to load and invoke callback? but if called implicitly it should be loaded again? + if(obj.state.loaded) { + obj.state.loaded = false; + for(i = 0, j = obj.parents.length; i < j; i++) { + this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) { + return $.inArray(v, obj.children_d) === -1; + }); + } + for(k = 0, l = obj.children_d.length; k < l; k++) { + if(this._model.data[obj.children_d[k]].state.selected) { + c = true; + } + delete this._model.data[obj.children_d[k]]; + } + if (c) { + this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) { + return $.inArray(v, obj.children_d) === -1; + }); + } + obj.children = []; + obj.children_d = []; + if(c) { + this.trigger('changed', { 'action' : 'load_node', 'node' : obj, 'selected' : this._data.core.selected }); + } + } + obj.state.failed = false; + obj.state.loading = true; + this.get_node(obj, true).addClass("jstree-loading").attr('aria-busy',true); + this._load_node(obj, $.proxy(function (status) { + obj = this._model.data[obj.id]; + obj.state.loading = false; + obj.state.loaded = status; + obj.state.failed = !obj.state.loaded; + var dom = this.get_node(obj, true), i = 0, j = 0, m = this._model.data, has_children = false; + for(i = 0, j = obj.children.length; i < j; i++) { + if(m[obj.children[i]] && !m[obj.children[i]].state.hidden) { + has_children = true; + break; + } + } + if(obj.state.loaded && dom && dom.length) { + dom.removeClass('jstree-closed jstree-open jstree-leaf'); + if (!has_children) { + dom.addClass('jstree-leaf'); + } + else { + if (obj.id !== '#') { + dom.addClass(obj.state.opened ? 'jstree-open' : 'jstree-closed'); + } + } + } + dom.removeClass("jstree-loading").attr('aria-busy',false); + /** + * triggered after a node is loaded + * @event + * @name load_node.jstree + * @param {Object} node the node that was loading + * @param {Boolean} status was the node loaded successfully + */ + this.trigger('load_node', { "node" : obj, "status" : status }); + if(callback) { + callback.call(this, obj, status); + } + }, this)); + return true; + }, + /** + * load an array of nodes (will also load unavailable nodes as soon as the appear in the structure). Used internally. + * @private + * @name _load_nodes(nodes [, callback]) + * @param {array} nodes + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - the array passed to _load_nodes + */ + _load_nodes : function (nodes, callback, is_callback, force_reload) { + var r = true, + c = function () { this._load_nodes(nodes, callback, true); }, + m = this._model.data, i, j, tmp = []; + for(i = 0, j = nodes.length; i < j; i++) { + if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || (!is_callback && force_reload) )) { + if(!this.is_loading(nodes[i])) { + this.load_node(nodes[i], c); + } + r = false; + } + } + if(r) { + for(i = 0, j = nodes.length; i < j; i++) { + if(m[nodes[i]] && m[nodes[i]].state.loaded) { + tmp.push(nodes[i]); + } + } + if(callback && !callback.done) { + callback.call(this, tmp); + callback.done = true; + } + } + }, + /** + * loads all unloaded nodes + * @name load_all([obj, callback]) + * @param {mixed} obj the node to load recursively, omit to load all nodes in the tree + * @param {function} callback a function to be executed once loading all the nodes is complete, + * @trigger load_all.jstree + */ + load_all : function (obj, callback) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var to_load = [], + m = this._model.data, + c = m[obj.id].children_d, + i, j; + if(obj.state && !obj.state.loaded) { + to_load.push(obj.id); + } + for(i = 0, j = c.length; i < j; i++) { + if(m[c[i]] && m[c[i]].state && !m[c[i]].state.loaded) { + to_load.push(c[i]); + } + } + if(to_load.length) { + this._load_nodes(to_load, function () { + this.load_all(obj, callback); + }); + } + else { + /** + * triggered after a load_all call completes + * @event + * @name load_all.jstree + * @param {Object} node the recursively loaded node + */ + if(callback) { callback.call(this, obj); } + this.trigger('load_all', { "node" : obj }); + } + }, + /** + * handles the actual loading of a node. Used only internally. + * @private + * @name _load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - a boolean status + * @return {Boolean} + */ + _load_node : function (obj, callback) { + var s = this.settings.core.data, t; + var notTextOrCommentNode = function notTextOrCommentNode () { + return this.nodeType !== 3 && this.nodeType !== 8; + }; + // use original HTML + if(!s) { + if(obj.id === $.jstree.root) { + return this._append_html_data(obj, this._data.core.original_container_html.clone(true), function (status) { + callback.call(this, status); + }); + } + else { + return callback.call(this, false); + } + // return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false); + } + if($.isFunction(s)) { + return s.call(this, obj, $.proxy(function (d) { + if(d === false) { + callback.call(this, false); + } + else { + this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(notTextOrCommentNode) : d, function (status) { + callback.call(this, status); + }); + } + // return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d)); + }, this)); + } + if(typeof s === 'object') { + if(s.url) { + s = $.extend(true, {}, s); + if($.isFunction(s.url)) { + s.url = s.url.call(this, obj); + } + if($.isFunction(s.data)) { + s.data = s.data.call(this, obj); + } + return $.ajax(s) + .done($.proxy(function (d,t,x) { + var type = x.getResponseHeader('Content-Type'); + if((type && type.indexOf('json') !== -1) || typeof d === "object") { + return this._append_json_data(obj, d, function (status) { callback.call(this, status); }); + //return callback.call(this, this._append_json_data(obj, d)); + } + if((type && type.indexOf('html') !== -1) || typeof d === "string") { + return this._append_html_data(obj, $($.parseHTML(d)).filter(notTextOrCommentNode), function (status) { callback.call(this, status); }); + // return callback.call(this, this._append_html_data(obj, $(d))); + } + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + }, this)) + .fail($.proxy(function (f) { + callback.call(this, false); + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)); + } + t = ($.isArray(s) || $.isPlainObject(s)) ? JSON.parse(JSON.stringify(s)) : s; + if(obj.id === $.jstree.root) { + return this._append_json_data(obj, t, function (status) { + callback.call(this, status); + }); + } + else { + this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_05', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + } + //return callback.call(this, (obj.id === $.jstree.root ? this._append_json_data(obj, t) : false) ); + } + if(typeof s === 'string') { + if(obj.id === $.jstree.root) { + return this._append_html_data(obj, $($.parseHTML(s)).filter(notTextOrCommentNode), function (status) { + callback.call(this, status); + }); + } + else { + this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_06', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + } + //return callback.call(this, (obj.id === $.jstree.root ? this._append_html_data(obj, $(s)) : false) ); + } + return callback.call(this, false); + }, + /** + * adds a node to the list of nodes to redraw. Used only internally. + * @private + * @name _node_changed(obj [, callback]) + * @param {mixed} obj + */ + _node_changed : function (obj) { + obj = this.get_node(obj); + if(obj) { + this._model.changed.push(obj.id); + } + }, + /** + * appends HTML content to the tree. Used internally. + * @private + * @name _append_html_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the HTML string to parse and append + * @trigger model.jstree, changed.jstree + */ + _append_html_data : function (dom, data, cb) { + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + var dat = data.is('ul') ? data.children() : data, + par = dom.id, + chd = [], + dpc = [], + m = this._model.data, + p = m[par], + s = this._data.core.selected.length, + tmp, i, j; + dat.each($.proxy(function (i, v) { + tmp = this._parse_model_from_html($(v), par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + }, this)); + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + /** + * triggered when new data is inserted to the tree model + * @event + * @name model.jstree + * @param {Array} nodes an array of node IDs + * @param {String} parent the parent ID of the nodes + */ + this.trigger('model', { "nodes" : dpc, 'parent' : par }); + if(par !== $.jstree.root) { + this._node_changed(par); + this.redraw(); + } + else { + this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(this._data.core.selected.length !== s) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + cb.call(this, true); + }, + /** + * appends JSON content to the tree. Used internally. + * @private + * @name _append_json_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the JSON object to parse and append + * @param {Boolean} force_processing internal param - do not set + * @trigger model.jstree, changed.jstree + */ + _append_json_data : function (dom, data, cb, force_processing) { + if(this.element === null) { return; } + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + // *%$@!!! + if(data.d) { + data = data.d; + if(typeof data === "string") { + data = JSON.parse(data); + } + } + if(!$.isArray(data)) { data = [data]; } + var w = null, + args = { + 'df' : this._model.default_state, + 'dat' : data, + 'par' : dom.id, + 'm' : this._model.data, + 't_id' : this._id, + 't_cnt' : this._cnt, + 'sel' : this._data.core.selected + }, + func = function (data, undefined) { + if(data.data) { data = data.data; } + var dat = data.dat, + par = data.par, + chd = [], + dpc = [], + add = [], + df = data.df, + t_id = data.t_id, + t_cnt = data.t_cnt, + m = data.m, + p = m[par], + sel = data.sel, + tmp, i, j, rslt, + parse_flat = function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = d.id.toString(), + i, j, c, e, + tmp = { + id : tid, + text : d.text || '', + icon : d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : d.children || [], + children_d : d.children_d || [], + data : d.data, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tid; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + m[tmp.id] = tmp; + for(i = 0, j = tmp.children.length; i < j; i++) { + c = parse_flat(m[tmp.children[i]], tmp.id, ps); + e = m[c]; + tmp.children_d.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + delete d.data; + delete d.children; + m[tmp.id].original = d; + if(tmp.state.selected) { + add.push(tmp.id); + } + return tmp.id; + }, + parse_nest = function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = false, i, j, c, e, tmp; + do { + tid = 'j' + t_id + '_' + (++t_cnt); + } while(m[tid]); + + tmp = { + id : false, + text : typeof d === 'string' ? d : '', + icon : typeof d === 'object' && d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.id) { tmp.id = d.id.toString(); } + if(d && d.text) { tmp.text = d.text; } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(tmp.li_attr.id && !tmp.id) { + tmp.id = tmp.li_attr.id.toString(); + } + if(!tmp.id) { + tmp.id = tid; + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tmp.id; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children.length) { + for(i = 0, j = d.children.length; i < j; i++) { + c = parse_nest(d.children[i], tmp.id, ps); + e = m[c]; + tmp.children.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + tmp.children_d = tmp.children_d.concat(tmp.children); + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + delete d.data; + delete d.children; + tmp.original = d; + m[tmp.id] = tmp; + if(tmp.state.selected) { + add.push(tmp.id); + } + return tmp.id; + }; + + if(dat.length && dat[0].id !== undefined && dat[0].parent !== undefined) { + // Flat JSON support (for easy import from DB): + // 1) convert to object (foreach) + for(i = 0, j = dat.length; i < j; i++) { + if(!dat[i].children) { + dat[i].children = []; + } + m[dat[i].id.toString()] = dat[i]; + } + // 2) populate children (foreach) + for(i = 0, j = dat.length; i < j; i++) { + m[dat[i].parent.toString()].children.push(dat[i].id.toString()); + // populate parent.children_d + p.children_d.push(dat[i].id.toString()); + } + // 3) normalize && populate parents and children_d with recursion + for(i = 0, j = p.children.length; i < j; i++) { + tmp = parse_flat(m[p.children[i]], par, p.parents.concat()); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + // ?) three_state selection - p.state.selected && t - (if three_state foreach(dat => ch) -> foreach(parents) if(parent.selected) child.selected = true; + rslt = { + 'cnt' : t_cnt, + 'mod' : m, + 'sel' : sel, + 'par' : par, + 'dpc' : dpc, + 'add' : add + }; + } + else { + for(i = 0, j = dat.length; i < j; i++) { + tmp = parse_nest(dat[i], par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + } + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + rslt = { + 'cnt' : t_cnt, + 'mod' : m, + 'sel' : sel, + 'par' : par, + 'dpc' : dpc, + 'add' : add + }; + } + if(typeof window === 'undefined' || typeof window.document === 'undefined') { + postMessage(rslt); + } + else { + return rslt; + } + }, + rslt = function (rslt, worker) { + if(this.element === null) { return; } + this._cnt = rslt.cnt; + var i, m = this._model.data; + for (i in m) { + if (m.hasOwnProperty(i) && m[i].state && m[i].state.loading && rslt.mod[i]) { + rslt.mod[i].state.loading = true; + } + } + this._model.data = rslt.mod; // breaks the reference in load_node - careful + + if(worker) { + var j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice(); + m = this._model.data; + // if selection was changed while calculating in worker + if(r.length !== s.length || $.vakata.array_unique(r.concat(s)).length !== r.length) { + // deselect nodes that are no longer selected + for(i = 0, j = r.length; i < j; i++) { + if($.inArray(r[i], a) === -1 && $.inArray(r[i], s) === -1) { + m[r[i]].state.selected = false; + } + } + // select nodes that were selected in the mean time + for(i = 0, j = s.length; i < j; i++) { + if($.inArray(s[i], r) === -1) { + m[s[i]].state.selected = true; + } + } + } + } + if(rslt.add.length) { + this._data.core.selected = this._data.core.selected.concat(rslt.add); + } + + this.trigger('model', { "nodes" : rslt.dpc, 'parent' : rslt.par }); + + if(rslt.par !== $.jstree.root) { + this._node_changed(rslt.par); + this.redraw(); + } + else { + // this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(rslt.add.length) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + cb.call(this, true); + }; + if(this.settings.core.worker && window.Blob && window.URL && window.Worker) { + try { + if(this._wrk === null) { + this._wrk = window.URL.createObjectURL( + new window.Blob( + ['self.onmessage = ' + func.toString()], + {type:"text/javascript"} + ) + ); + } + if(!this._data.core.working || force_processing) { + this._data.core.working = true; + w = new window.Worker(this._wrk); + w.onmessage = $.proxy(function (e) { + rslt.call(this, e.data, true); + try { w.terminate(); w = null; } catch(ignore) { } + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + }, this); + if(!args.par) { + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + } + else { + w.postMessage(args); + } + } + else { + this._data.core.worker_queue.push([dom, data, cb, true]); + } + } + catch(e) { + rslt.call(this, func(args), false); + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + } + } + else { + rslt.call(this, func(args), false); + } + }, + /** + * parses a node from a jQuery object and appends them to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_html(d [, p, ps]) + * @param {jQuery} d the jQuery object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_html : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = [].concat(ps); } + if(p) { ps.unshift(p); } + var c, e, m = this._model.data, + data = { + id : false, + text : false, + icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }, i, tmp, tid; + for(i in this._model.default_state) { + if(this._model.default_state.hasOwnProperty(i)) { + data.state[i] = this._model.default_state[i]; + } + } + tmp = $.vakata.attributes(d, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(!v.length) { return true; } + data.li_attr[i] = v; + if(i === 'id') { + data.id = v.toString(); + } + }); + tmp = d.children('a').first(); + if(tmp.length) { + tmp = $.vakata.attributes(tmp, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(v.length) { + data.a_attr[i] = v; + } + }); + } + tmp = d.children("a").first().length ? d.children("a").first().clone() : d.clone(); + tmp.children("ins, i, ul").remove(); + tmp = tmp.html(); + tmp = $('<div />').html(tmp); + data.text = this.settings.core.force_text ? tmp.text() : tmp.html(); + tmp = d.data(); + data.data = tmp ? $.extend(true, {}, tmp) : null; + data.state.opened = d.hasClass('jstree-open'); + data.state.selected = d.children('a').hasClass('jstree-clicked'); + data.state.disabled = d.children('a').hasClass('jstree-disabled'); + if(data.data && data.data.jstree) { + for(i in data.data.jstree) { + if(data.data.jstree.hasOwnProperty(i)) { + data.state[i] = data.data.jstree[i]; + } + } + } + tmp = d.children("a").children(".jstree-themeicon"); + if(tmp.length) { + data.icon = tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel'); + } + if(data.state.icon !== undefined) { + data.icon = data.state.icon; + } + if(data.icon === undefined || data.icon === null || data.icon === "") { + data.icon = true; + } + tmp = d.children("ul").children("li"); + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + data.id = data.li_attr.id ? data.li_attr.id.toString() : tid; + if(tmp.length) { + tmp.each($.proxy(function (i, v) { + c = this._parse_model_from_html($(v), data.id, ps); + e = this._model.data[c]; + data.children.push(c); + if(e.children_d.length) { + data.children_d = data.children_d.concat(e.children_d); + } + }, this)); + data.children_d = data.children_d.concat(data.children); + } + else { + if(d.hasClass('jstree-closed')) { + data.state.loaded = false; + } + } + if(data.li_attr['class']) { + data.li_attr['class'] = data.li_attr['class'].replace('jstree-closed','').replace('jstree-open',''); + } + if(data.a_attr['class']) { + data.a_attr['class'] = data.a_attr['class'].replace('jstree-clicked','').replace('jstree-disabled',''); + } + m[data.id] = data; + if(data.state.selected) { + this._data.core.selected.push(data.id); + } + return data.id; + }, + /** + * parses a node from a JSON object (used when dealing with flat data, which has no nesting of children, but has id and parent properties) and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_flat_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_flat_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = d.id.toString(), + m = this._model.data, + df = this._model.default_state, + i, j, c, e, + tmp = { + id : tid, + text : d.text || '', + icon : d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : d.children || [], + children_d : d.children_d || [], + data : d.data, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tid; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + m[tmp.id] = tmp; + for(i = 0, j = tmp.children.length; i < j; i++) { + c = this._parse_model_from_flat_json(m[tmp.children[i]], tmp.id, ps); + e = m[c]; + tmp.children_d.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + delete d.data; + delete d.children; + m[tmp.id].original = d; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * parses a node from a JSON object and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = false, i, j, c, e, m = this._model.data, df = this._model.default_state, tmp; + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + + tmp = { + id : false, + text : typeof d === 'string' ? d : '', + icon : typeof d === 'object' && d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.id) { tmp.id = d.id.toString(); } + if(d && d.text) { tmp.text = d.text; } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(tmp.li_attr.id && !tmp.id) { + tmp.id = tmp.li_attr.id.toString(); + } + if(!tmp.id) { + tmp.id = tid; + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tmp.id; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children.length) { + for(i = 0, j = d.children.length; i < j; i++) { + c = this._parse_model_from_json(d.children[i], tmp.id, ps); + e = m[c]; + tmp.children.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + tmp.children_d = tmp.children_d.concat(tmp.children); + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + delete d.data; + delete d.children; + tmp.original = d; + m[tmp.id] = tmp; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * redraws all nodes that need to be redrawn. Used internally. + * @private + * @name _redraw() + * @trigger redraw.jstree + */ + _redraw : function () { + var nodes = this._model.force_full_redraw ? this._model.data[$.jstree.root].children.concat([]) : this._model.changed.concat([]), + f = document.createElement('UL'), tmp, i, j, fe = this._data.core.focused; + for(i = 0, j = nodes.length; i < j; i++) { + tmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw); + if(tmp && this._model.force_full_redraw) { + f.appendChild(tmp); + } + } + if(this._model.force_full_redraw) { + f.className = this.get_container_ul()[0].className; + f.setAttribute('role','group'); + this.element.empty().append(f); + //this.get_container_ul()[0].appendChild(f); + } + if(fe !== null) { + tmp = this.get_node(fe, true); + if(tmp && tmp.length && tmp.children('.jstree-anchor')[0] !== document.activeElement) { + tmp.children('.jstree-anchor').focus(); + } + else { + this._data.core.focused = null; + } + } + this._model.force_full_redraw = false; + this._model.changed = []; + /** + * triggered after nodes are redrawn + * @event + * @name redraw.jstree + * @param {array} nodes the redrawn nodes + */ + this.trigger('redraw', { "nodes" : nodes }); + }, + /** + * redraws all nodes that need to be redrawn or optionally - the whole tree + * @name redraw([full]) + * @param {Boolean} full if set to `true` all nodes are redrawn. + */ + redraw : function (full) { + if(full) { + this._model.force_full_redraw = true; + } + //if(this._model.redraw_timeout) { + // clearTimeout(this._model.redraw_timeout); + //} + //this._model.redraw_timeout = setTimeout($.proxy(this._redraw, this),0); + this._redraw(); + }, + /** + * redraws a single node's children. Used internally. + * @private + * @name draw_children(node) + * @param {mixed} node the node whose children will be redrawn + */ + draw_children : function (node) { + var obj = this.get_node(node), + i = false, + j = false, + k = false, + d = document; + if(!obj) { return false; } + if(obj.id === $.jstree.root) { return this.redraw(true); } + node = this.get_node(node, true); + if(!node || !node.length) { return false; } // TODO: quick toggle + + node.children('.jstree-children').remove(); + node = node[0]; + if(obj.children.length && obj.state.loaded) { + k = d.createElement('UL'); + k.setAttribute('role', 'group'); + k.className = 'jstree-children'; + for(i = 0, j = obj.children.length; i < j; i++) { + k.appendChild(this.redraw_node(obj.children[i], true, true)); + } + node.appendChild(k); + } + }, + /** + * redraws a single node. Used internally. + * @private + * @name redraw_node(node, deep, is_callback, force_render) + * @param {mixed} node the node to redraw + * @param {Boolean} deep should child nodes be redrawn too + * @param {Boolean} is_callback is this a recursion call + * @param {Boolean} force_render should children of closed parents be drawn anyway + */ + redraw_node : function (node, deep, is_callback, force_render) { + var obj = this.get_node(node), + par = false, + ind = false, + old = false, + i = false, + j = false, + k = false, + c = '', + d = document, + m = this._model.data, + f = false, + s = false, + tmp = null, + t = 0, + l = 0, + has_children = false, + last_sibling = false; + if(!obj) { return false; } + if(obj.id === $.jstree.root) { return this.redraw(true); } + deep = deep || obj.children.length === 0; + node = !document.querySelector ? document.getElementById(obj.id) : this.element[0].querySelector('#' + ("0123456789".indexOf(obj.id[0]) !== -1 ? '\\3' + obj.id[0] + ' ' + obj.id.substr(1).replace($.jstree.idregex,'\\$&') : obj.id.replace($.jstree.idregex,'\\$&')) ); //, this.element); + if(!node) { + deep = true; + //node = d.createElement('LI'); + if(!is_callback) { + par = obj.parent !== $.jstree.root ? $('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null; + if(par !== null && (!par || !m[obj.parent].state.opened)) { + return false; + } + ind = $.inArray(obj.id, par === null ? m[$.jstree.root].children : m[obj.parent].children); + } + } + else { + node = $(node); + if(!is_callback) { + par = node.parent().parent()[0]; + if(par === this.element[0]) { + par = null; + } + ind = node.index(); + } + // m[obj.id].data = node.data(); // use only node's data, no need to touch jquery storage + if(!deep && obj.children.length && !node.children('.jstree-children').length) { + deep = true; + } + if(!deep) { + old = node.children('.jstree-children')[0]; + } + f = node.children('.jstree-anchor')[0] === document.activeElement; + node.remove(); + //node = d.createElement('LI'); + //node = node[0]; + } + node = this._data.core.node.cloneNode(true); + // node is DOM, deep is boolean + + c = 'jstree-node '; + for(i in obj.li_attr) { + if(obj.li_attr.hasOwnProperty(i)) { + if(i === 'id') { continue; } + if(i !== 'class') { + node.setAttribute(i, obj.li_attr[i]); + } + else { + c += obj.li_attr[i]; + } + } + } + if(!obj.a_attr.id) { + obj.a_attr.id = obj.id + '_anchor'; + } + node.setAttribute('aria-selected', !!obj.state.selected); + node.setAttribute('aria-level', obj.parents.length); + node.setAttribute('aria-labelledby', obj.a_attr.id); + if(obj.state.disabled) { + node.setAttribute('aria-disabled', true); + } + + for(i = 0, j = obj.children.length; i < j; i++) { + if(!m[obj.children[i]].state.hidden) { + has_children = true; + break; + } + } + if(obj.parent !== null && m[obj.parent] && !obj.state.hidden) { + i = $.inArray(obj.id, m[obj.parent].children); + last_sibling = obj.id; + if(i !== -1) { + i++; + for(j = m[obj.parent].children.length; i < j; i++) { + if(!m[m[obj.parent].children[i]].state.hidden) { + last_sibling = m[obj.parent].children[i]; + } + if(last_sibling !== obj.id) { + break; + } + } + } + } + + if(obj.state.hidden) { + c += ' jstree-hidden'; + } + if(obj.state.loaded && !has_children) { + c += ' jstree-leaf'; + } + else { + c += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed'; + node.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) ); + } + if(last_sibling === obj.id) { + c += ' jstree-last'; + } + node.id = obj.id; + node.className = c; + c = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : ''); + for(j in obj.a_attr) { + if(obj.a_attr.hasOwnProperty(j)) { + if(j === 'href' && obj.a_attr[j] === '#') { continue; } + if(j !== 'class') { + node.childNodes[1].setAttribute(j, obj.a_attr[j]); + } + else { + c += ' ' + obj.a_attr[j]; + } + } + } + if(c.length) { + node.childNodes[1].className = 'jstree-anchor ' + c; + } + if((obj.icon && obj.icon !== true) || obj.icon === false) { + if(obj.icon === false) { + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-hidden'; + } + else if(obj.icon.indexOf('/') === -1 && obj.icon.indexOf('.') === -1) { + node.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom'; + } + else { + node.childNodes[1].childNodes[0].style.backgroundImage = 'url("'+obj.icon+'")'; + node.childNodes[1].childNodes[0].style.backgroundPosition = 'center center'; + node.childNodes[1].childNodes[0].style.backgroundSize = 'auto'; + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom'; + } + } + + if(this.settings.core.force_text) { + node.childNodes[1].appendChild(d.createTextNode(obj.text)); + } + else { + node.childNodes[1].innerHTML += obj.text; + } + + + if(deep && obj.children.length && (obj.state.opened || force_render) && obj.state.loaded) { + k = d.createElement('UL'); + k.setAttribute('role', 'group'); + k.className = 'jstree-children'; + for(i = 0, j = obj.children.length; i < j; i++) { + k.appendChild(this.redraw_node(obj.children[i], deep, true)); + } + node.appendChild(k); + } + if(old) { + node.appendChild(old); + } + if(!is_callback) { + // append back using par / ind + if(!par) { + par = this.element[0]; + } + for(i = 0, j = par.childNodes.length; i < j; i++) { + if(par.childNodes[i] && par.childNodes[i].className && par.childNodes[i].className.indexOf('jstree-children') !== -1) { + tmp = par.childNodes[i]; + break; + } + } + if(!tmp) { + tmp = d.createElement('UL'); + tmp.setAttribute('role', 'group'); + tmp.className = 'jstree-children'; + par.appendChild(tmp); + } + par = tmp; + + if(ind < par.childNodes.length) { + par.insertBefore(node, par.childNodes[ind]); + } + else { + par.appendChild(node); + } + if(f) { + t = this.element[0].scrollTop; + l = this.element[0].scrollLeft; + node.childNodes[1].focus(); + this.element[0].scrollTop = t; + this.element[0].scrollLeft = l; + } + } + if(obj.state.opened && !obj.state.loaded) { + obj.state.opened = false; + setTimeout($.proxy(function () { + this.open_node(obj.id, false, 0); + }, this), 0); + } + return node; + }, + /** + * opens a node, revaling its children. If the node is not loaded it will be loaded and opened once ready. + * @name open_node(obj [, callback, animation]) + * @param {mixed} obj the node to open + * @param {Function} callback a function to execute once the node is opened + * @param {Number} animation the animation duration in milliseconds when opening the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger open_node.jstree, after_open.jstree, before_open.jstree + */ + open_node : function (obj, callback, animation) { + var t1, t2, d, t; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.open_node(obj[t1], callback, animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + if(!this.is_closed(obj)) { + if(callback) { + callback.call(this, obj, false); + } + return false; + } + if(!this.is_loaded(obj)) { + if(this.is_loading(obj)) { + return setTimeout($.proxy(function () { + this.open_node(obj, callback, animation); + }, this), 500); + } + this.load_node(obj, function (o, ok) { + return ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false); + }); + } + else { + d = this.get_node(obj, true); + t = this; + if(d.length) { + if(animation && d.children(".jstree-children").length) { + d.children(".jstree-children").stop(true, true); + } + if(obj.children.length && !this._firstChild(d.children('.jstree-children')[0])) { + this.draw_children(obj); + //d = this.get_node(obj, true); + } + if(!animation) { + this.trigger('before_open', { "node" : obj }); + d[0].className = d[0].className.replace('jstree-closed', 'jstree-open'); + d[0].setAttribute("aria-expanded", true); + } + else { + this.trigger('before_open', { "node" : obj }); + d + .children(".jstree-children").css("display","none").end() + .removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded", true) + .children(".jstree-children").stop(true, true) + .slideDown(animation, function () { + this.style.display = ""; + if (t.element) { + t.trigger("after_open", { "node" : obj }); + } + }); + } + } + obj.state.opened = true; + if(callback) { + callback.call(this, obj, true); + } + if(!d.length) { + /** + * triggered when a node is about to be opened (if the node is supposed to be in the DOM, it will be, but it won't be visible yet) + * @event + * @name before_open.jstree + * @param {Object} node the opened node + */ + this.trigger('before_open', { "node" : obj }); + } + /** + * triggered when a node is opened (if there is an animation it will not be completed yet) + * @event + * @name open_node.jstree + * @param {Object} node the opened node + */ + this.trigger('open_node', { "node" : obj }); + if(!animation || !d.length) { + /** + * triggered when a node is opened and the animation is complete + * @event + * @name after_open.jstree + * @param {Object} node the opened node + */ + this.trigger("after_open", { "node" : obj }); + } + return true; + } + }, + /** + * opens every parent of a node (node should be loaded) + * @name _open_to(obj) + * @param {mixed} obj the node to reveal + * @private + */ + _open_to : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + var i, j, p = obj.parents; + for(i = 0, j = p.length; i < j; i+=1) { + if(i !== $.jstree.root) { + this.open_node(p[i], false, 0); + } + } + return $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element); + }, + /** + * closes a node, hiding its children + * @name close_node(obj [, animation]) + * @param {mixed} obj the node to close + * @param {Number} animation the animation duration in milliseconds when closing the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger close_node.jstree, after_close.jstree + */ + close_node : function (obj, animation) { + var t1, t2, t, d; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.close_node(obj[t1], animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(this.is_closed(obj)) { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + t = this; + d = this.get_node(obj, true); + + obj.state.opened = false; + /** + * triggered when a node is closed (if there is an animation it will not be complete yet) + * @event + * @name close_node.jstree + * @param {Object} node the closed node + */ + this.trigger('close_node',{ "node" : obj }); + if(!d.length) { + /** + * triggered when a node is closed and the animation is complete + * @event + * @name after_close.jstree + * @param {Object} node the closed node + */ + this.trigger("after_close", { "node" : obj }); + } + else { + if(!animation) { + d[0].className = d[0].className.replace('jstree-open', 'jstree-closed'); + d.attr("aria-expanded", false).children('.jstree-children').remove(); + this.trigger("after_close", { "node" : obj }); + } + else { + d + .children(".jstree-children").attr("style","display:block !important").end() + .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false) + .children(".jstree-children").stop(true, true).slideUp(animation, function () { + this.style.display = ""; + d.children('.jstree-children').remove(); + if (t.element) { + t.trigger("after_close", { "node" : obj }); + } + }); + } + } + }, + /** + * toggles a node - closing it if it is open, opening it if it is closed + * @name toggle_node(obj) + * @param {mixed} obj the node to toggle + */ + toggle_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.toggle_node(obj[t1]); + } + return true; + } + if(this.is_closed(obj)) { + return this.open_node(obj); + } + if(this.is_open(obj)) { + return this.close_node(obj); + } + }, + /** + * opens all nodes within a node (or the tree), revaling their children. If the node is not loaded it will be loaded and opened once ready. + * @name open_all([obj, animation, original_obj]) + * @param {mixed} obj the node to open recursively, omit to open all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation + * @param {jQuery} reference to the node that started the process (internal use) + * @trigger open_all.jstree + */ + open_all : function (obj, animation, original_obj) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), i, j, _this; + if(!dom.length) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + if(this.is_closed(this._model.data[obj.children_d[i]])) { + this._model.data[obj.children_d[i]].state.opened = true; + } + } + return this.trigger('open_all', { "node" : obj }); + } + original_obj = original_obj || dom; + _this = this; + dom = this.is_closed(obj) ? dom.find('.jstree-closed').addBack() : dom.find('.jstree-closed'); + dom.each(function () { + _this.open_node( + this, + function(node, status) { if(status && this.is_parent(node)) { this.open_all(node, animation, original_obj); } }, + animation || 0 + ); + }); + if(original_obj.find('.jstree-closed').length === 0) { + /** + * triggered when an `open_all` call completes + * @event + * @name open_all.jstree + * @param {Object} node the opened node + */ + this.trigger('open_all', { "node" : this.get_node(original_obj) }); + } + }, + /** + * closes all nodes within a node (or the tree), revaling their children + * @name close_all([obj, animation]) + * @param {mixed} obj the node to close recursively, omit to close all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation + * @trigger close_all.jstree + */ + close_all : function (obj, animation) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), + _this = this, i, j; + if(dom.length) { + dom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open'); + $(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); }); + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].state.opened = false; + } + /** + * triggered when an `close_all` call completes + * @event + * @name close_all.jstree + * @param {Object} node the closed node + */ + this.trigger('close_all', { "node" : obj }); + }, + /** + * checks if a node is disabled (not selectable) + * @name is_disabled(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_disabled : function (obj) { + obj = this.get_node(obj); + return obj && obj.state && obj.state.disabled; + }, + /** + * enables a node - so that it can be selected + * @name enable_node(obj) + * @param {mixed} obj the node to enable + * @trigger enable_node.jstree + */ + enable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.enable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + obj.state.disabled = false; + this.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled').attr('aria-disabled', false); + /** + * triggered when an node is enabled + * @event + * @name enable_node.jstree + * @param {Object} node the enabled node + */ + this.trigger('enable_node', { 'node' : obj }); + }, + /** + * disables a node - so that it can not be selected + * @name disable_node(obj) + * @param {mixed} obj the node to disable + * @trigger disable_node.jstree + */ + disable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.disable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + obj.state.disabled = true; + this.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled').attr('aria-disabled', true); + /** + * triggered when an node is disabled + * @event + * @name disable_node.jstree + * @param {Object} node the disabled node + */ + this.trigger('disable_node', { 'node' : obj }); + }, + /** + * determines if a node is hidden + * @name is_hidden(obj) + * @param {mixed} obj the node + */ + is_hidden : function (obj) { + obj = this.get_node(obj); + return obj.state.hidden === true; + }, + /** + * hides a node - it is still in the structure but will not be visible + * @name hide_node(obj) + * @param {mixed} obj the node to hide + * @param {Boolean} skip_redraw internal parameter controlling if redraw is called + * @trigger hide_node.jstree + */ + hide_node : function (obj, skip_redraw) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.hide_node(obj[t1], true); + } + if (!skip_redraw) { + this.redraw(); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(!obj.state.hidden) { + obj.state.hidden = true; + this._node_changed(obj.parent); + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when an node is hidden + * @event + * @name hide_node.jstree + * @param {Object} node the hidden node + */ + this.trigger('hide_node', { 'node' : obj }); + } + }, + /** + * shows a node + * @name show_node(obj) + * @param {mixed} obj the node to show + * @param {Boolean} skip_redraw internal parameter controlling if redraw is called + * @trigger show_node.jstree + */ + show_node : function (obj, skip_redraw) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.show_node(obj[t1], true); + } + if (!skip_redraw) { + this.redraw(); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(obj.state.hidden) { + obj.state.hidden = false; + this._node_changed(obj.parent); + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when an node is shown + * @event + * @name show_node.jstree + * @param {Object} node the shown node + */ + this.trigger('show_node', { 'node' : obj }); + } + }, + /** + * hides all nodes + * @name hide_all() + * @trigger hide_all.jstree + */ + hide_all : function (skip_redraw) { + var i, m = this._model.data, ids = []; + for(i in m) { + if(m.hasOwnProperty(i) && i !== $.jstree.root && !m[i].state.hidden) { + m[i].state.hidden = true; + ids.push(i); + } + } + this._model.force_full_redraw = true; + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when all nodes are hidden + * @event + * @name hide_all.jstree + * @param {Array} nodes the IDs of all hidden nodes + */ + this.trigger('hide_all', { 'nodes' : ids }); + return ids; + }, + /** + * shows all nodes + * @name show_all() + * @trigger show_all.jstree + */ + show_all : function (skip_redraw) { + var i, m = this._model.data, ids = []; + for(i in m) { + if(m.hasOwnProperty(i) && i !== $.jstree.root && m[i].state.hidden) { + m[i].state.hidden = false; + ids.push(i); + } + } + this._model.force_full_redraw = true; + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when all nodes are shown + * @event + * @name show_all.jstree + * @param {Array} nodes the IDs of all shown nodes + */ + this.trigger('show_all', { 'nodes' : ids }); + return ids; + }, + /** + * called when a node is selected by the user. Used internally. + * @private + * @name activate_node(obj, e) + * @param {mixed} obj the node + * @param {Object} e the related event + * @trigger activate_node.jstree, changed.jstree + */ + activate_node : function (obj, e) { + if(this.is_disabled(obj)) { + return false; + } + if(!e || typeof e !== 'object') { + e = {}; + } + + // ensure last_clicked is still in the DOM, make it fresh (maybe it was moved?) and make sure it is still selected, if not - make last_clicked the last selected node + this._data.core.last_clicked = this._data.core.last_clicked && this._data.core.last_clicked.id !== undefined ? this.get_node(this._data.core.last_clicked.id) : null; + if(this._data.core.last_clicked && !this._data.core.last_clicked.state.selected) { this._data.core.last_clicked = null; } + if(!this._data.core.last_clicked && this._data.core.selected.length) { this._data.core.last_clicked = this.get_node(this._data.core.selected[this._data.core.selected.length - 1]); } + + if(!this.settings.core.multiple || (!e.metaKey && !e.ctrlKey && !e.shiftKey) || (e.shiftKey && (!this._data.core.last_clicked || !this.get_parent(obj) || this.get_parent(obj) !== this._data.core.last_clicked.parent ) )) { + if(!this.settings.core.multiple && (e.metaKey || e.ctrlKey || e.shiftKey) && this.is_selected(obj)) { + this.deselect_node(obj, false, e); + } + else { + this.deselect_all(true); + this.select_node(obj, false, false, e); + this._data.core.last_clicked = this.get_node(obj); + } + } + else { + if(e.shiftKey) { + var o = this.get_node(obj).id, + l = this._data.core.last_clicked.id, + p = this.get_node(this._data.core.last_clicked.parent).children, + c = false, + i, j; + for(i = 0, j = p.length; i < j; i += 1) { + // separate IFs work whem o and l are the same + if(p[i] === o) { + c = !c; + } + if(p[i] === l) { + c = !c; + } + if(!this.is_disabled(p[i]) && (c || p[i] === o || p[i] === l)) { + if (!this.is_hidden(p[i])) { + this.select_node(p[i], true, false, e); + } + } + else { + this.deselect_node(p[i], true, e); + } + } + this.trigger('changed', { 'action' : 'select_node', 'node' : this.get_node(obj), 'selected' : this._data.core.selected, 'event' : e }); + } + else { + if(!this.is_selected(obj)) { + this.select_node(obj, false, false, e); + } + else { + this.deselect_node(obj, false, e); + } + } + } + /** + * triggered when an node is clicked or intercated with by the user + * @event + * @name activate_node.jstree + * @param {Object} node + * @param {Object} event the ooriginal event (if any) which triggered the call (may be an empty object) + */ + this.trigger('activate_node', { 'node' : this.get_node(obj), 'event' : e }); + }, + /** + * applies the hover state on a node, called when a node is hovered by the user. Used internally. + * @private + * @name hover_node(obj) + * @param {mixed} obj + * @trigger hover_node.jstree + */ + hover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || obj.children('.jstree-hovered').length) { + return false; + } + var o = this.element.find('.jstree-hovered'), t = this.element; + if(o && o.length) { this.dehover_node(o); } + + obj.children('.jstree-anchor').addClass('jstree-hovered'); + /** + * triggered when an node is hovered + * @event + * @name hover_node.jstree + * @param {Object} node + */ + this.trigger('hover_node', { 'node' : this.get_node(obj) }); + setTimeout(function () { t.attr('aria-activedescendant', obj[0].id); }, 0); + }, + /** + * removes the hover state from a nodecalled when a node is no longer hovered by the user. Used internally. + * @private + * @name dehover_node(obj) + * @param {mixed} obj + * @trigger dehover_node.jstree + */ + dehover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || !obj.children('.jstree-hovered').length) { + return false; + } + obj.children('.jstree-anchor').removeClass('jstree-hovered'); + /** + * triggered when an node is no longer hovered + * @event + * @name dehover_node.jstree + * @param {Object} node + */ + this.trigger('dehover_node', { 'node' : this.get_node(obj) }); + }, + /** + * select a node + * @name select_node(obj [, supress_event, prevent_open]) + * @param {mixed} obj an array can be used to select multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @param {Boolean} prevent_open if set to `true` parents of the selected node won't be opened + * @trigger select_node.jstree, changed.jstree + */ + select_node : function (obj, supress_event, prevent_open, e) { + var dom, t1, t2, th; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.select_node(obj[t1], supress_event, prevent_open, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.selected) { + obj.state.selected = true; + this._data.core.selected.push(obj.id); + if(!prevent_open) { + dom = this._open_to(obj); + } + if(dom && dom.length) { + dom.attr('aria-selected', true).children('.jstree-anchor').addClass('jstree-clicked'); + } + /** + * triggered when an node is selected + * @event + * @name select_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this select_node + */ + this.trigger('select_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + /** + * triggered when selection changes + * @event + * @name changed.jstree + * @param {Object} node + * @param {Object} action the action that caused the selection to change + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this changed event + */ + this.trigger('changed', { 'action' : 'select_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * deselect a node + * @name deselect_node(obj [, supress_event]) + * @param {mixed} obj an array can be used to deselect multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_node.jstree, changed.jstree + */ + deselect_node : function (obj, supress_event, e) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.deselect_node(obj[t1], supress_event, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.selected) { + obj.state.selected = false; + this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id); + if(dom.length) { + dom.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-clicked'); + } + /** + * triggered when an node is deselected + * @event + * @name deselect_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this deselect_node + */ + this.trigger('deselect_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * select all nodes in the tree + * @name select_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger select_all.jstree, changed.jstree + */ + select_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + this._data.core.selected = this._model.data[$.jstree.root].children_d.concat(); + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = true; + } + } + this.redraw(true); + /** + * triggered when all nodes are selected + * @event + * @name select_all.jstree + * @param {Array} selected the current selection + */ + this.trigger('select_all', { 'selected' : this._data.core.selected }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'select_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * deselect all selected nodes + * @name deselect_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_all.jstree, changed.jstree + */ + deselect_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = false; + } + } + this._data.core.selected = []; + this.element.find('.jstree-clicked').removeClass('jstree-clicked').parent().attr('aria-selected', false); + /** + * triggered when all nodes are deselected + * @event + * @name deselect_all.jstree + * @param {Object} node the previous selection + * @param {Array} selected the current selection + */ + this.trigger('deselect_all', { 'selected' : this._data.core.selected, 'node' : tmp }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * checks if a node is selected + * @name is_selected(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_selected : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + return obj.state.selected; + }, + /** + * get an array of all selected nodes + * @name get_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_selected : function (full) { + return full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected.slice(); + }, + /** + * get an array of all top level selected nodes (ignoring children of selected nodes) + * @name get_top_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_top_selected : function (full) { + var tmp = this.get_selected(true), + obj = {}, i, j, k, l; + for(i = 0, j = tmp.length; i < j; i++) { + obj[tmp[i].id] = tmp[i]; + } + for(i = 0, j = tmp.length; i < j; i++) { + for(k = 0, l = tmp[i].children_d.length; k < l; k++) { + if(obj[tmp[i].children_d[k]]) { + delete obj[tmp[i].children_d[k]]; + } + } + } + tmp = []; + for(i in obj) { + if(obj.hasOwnProperty(i)) { + tmp.push(i); + } + } + return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp; + }, + /** + * get an array of all bottom level selected nodes (ignoring selected parents) + * @name get_bottom_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_bottom_selected : function (full) { + var tmp = this.get_selected(true), + obj = [], i, j; + for(i = 0, j = tmp.length; i < j; i++) { + if(!tmp[i].children.length) { + obj.push(tmp[i].id); + } + } + return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj; + }, + /** + * gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally. + * @name get_state() + * @private + * @return {Object} + */ + get_state : function () { + var state = { + 'core' : { + 'open' : [], + 'scroll' : { + 'left' : this.element.scrollLeft(), + 'top' : this.element.scrollTop() + }, + /*! + 'themes' : { + 'name' : this.get_theme(), + 'icons' : this._data.core.themes.icons, + 'dots' : this._data.core.themes.dots + }, + */ + 'selected' : [] + } + }, i; + for(i in this._model.data) { + if(this._model.data.hasOwnProperty(i)) { + if(i !== $.jstree.root) { + if(this._model.data[i].state.opened) { + state.core.open.push(i); + } + if(this._model.data[i].state.selected) { + state.core.selected.push(i); + } + } + } + } + return state; + }, + /** + * sets the state of the tree. Used internally. + * @name set_state(state [, callback]) + * @private + * @param {Object} state the state to restore. Keep in mind this object is passed by reference and jstree will modify it. + * @param {Function} callback an optional function to execute once the state is restored. + * @trigger set_state.jstree + */ + set_state : function (state, callback) { + if(state) { + if(state.core) { + var res, n, t, _this, i; + if(state.core.open) { + if(!$.isArray(state.core.open) || !state.core.open.length) { + delete state.core.open; + this.set_state(state, callback); + } + else { + this._load_nodes(state.core.open, function (nodes) { + this.open_node(nodes, false, 0); + delete state.core.open; + this.set_state(state, callback); + }); + } + return false; + } + if(state.core.scroll) { + if(state.core.scroll && state.core.scroll.left !== undefined) { + this.element.scrollLeft(state.core.scroll.left); + } + if(state.core.scroll && state.core.scroll.top !== undefined) { + this.element.scrollTop(state.core.scroll.top); + } + delete state.core.scroll; + this.set_state(state, callback); + return false; + } + if(state.core.selected) { + _this = this; + this.deselect_all(); + $.each(state.core.selected, function (i, v) { + _this.select_node(v, false, true); + }); + delete state.core.selected; + this.set_state(state, callback); + return false; + } + for(i in state) { + if(state.hasOwnProperty(i) && i !== "core" && $.inArray(i, this.settings.plugins) === -1) { + delete state[i]; + } + } + if($.isEmptyObject(state.core)) { + delete state.core; + this.set_state(state, callback); + return false; + } + } + if($.isEmptyObject(state)) { + state = null; + if(callback) { callback.call(this); } + /** + * triggered when a `set_state` call completes + * @event + * @name set_state.jstree + */ + this.trigger('set_state'); + return false; + } + return true; + } + return false; + }, + /** + * refreshes the tree - all nodes are reloaded with calls to `load_node`. + * @name refresh() + * @param {Boolean} skip_loading an option to skip showing the loading indicator + * @param {Mixed} forget_state if set to `true` state will not be reapplied, if set to a function (receiving the current state as argument) the result of that function will be used as state + * @trigger refresh.jstree + */ + refresh : function (skip_loading, forget_state) { + this._data.core.state = forget_state === true ? {} : this.get_state(); + if(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); } + this._cnt = 0; + this._model.data = {}; + this._model.data[$.jstree.root] = { + id : $.jstree.root, + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + }; + this._data.core.selected = []; + this._data.core.last_clicked = null; + this._data.core.focused = null; + + var c = this.get_container_ul()[0].className; + if(!skip_loading) { + this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>"); + this.element.attr('aria-activedescendant','j'+this._id+'_loading'); + } + this.load_node($.jstree.root, function (o, s) { + if(s) { + this.get_container_ul()[0].className = c; + if(this._firstChild(this.get_container_ul()[0])) { + this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id); + } + this.set_state($.extend(true, {}, this._data.core.state), function () { + /** + * triggered when a `refresh` call completes + * @event + * @name refresh.jstree + */ + this.trigger('refresh'); + }); + } + this._data.core.state = null; + }); + }, + /** + * refreshes a node in the tree (reload its children) all opened nodes inside that node are reloaded with calls to `load_node`. + * @name refresh_node(obj) + * @param {mixed} obj the node + * @trigger refresh_node.jstree + */ + refresh_node : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var opened = [], to_load = [], s = this._data.core.selected.concat([]); + to_load.push(obj.id); + if(obj.state.opened === true) { opened.push(obj.id); } + this.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); }); + this._load_nodes(to_load, $.proxy(function (nodes) { + this.open_node(opened, false, 0); + this.select_node(s); + /** + * triggered when a node is refreshed + * @event + * @name refresh_node.jstree + * @param {Object} node - the refreshed node + * @param {Array} nodes - an array of the IDs of the nodes that were reloaded + */ + this.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes }); + }, this), false, true); + }, + /** + * set (change) the ID of a node + * @name set_id(obj, id) + * @param {mixed} obj the node + * @param {String} id the new ID + * @return {Boolean} + * @trigger set_id.jstree + */ + set_id : function (obj, id) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var i, j, m = this._model.data, old = obj.id; + id = id.toString(); + // update parents (replace current ID with new one in children and children_d) + m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id; + for(i = 0, j = obj.parents.length; i < j; i++) { + m[obj.parents[i]].children_d[$.inArray(obj.id, m[obj.parents[i]].children_d)] = id; + } + // update children (replace current ID with new one in parent and parents) + for(i = 0, j = obj.children.length; i < j; i++) { + m[obj.children[i]].parent = id; + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + m[obj.children_d[i]].parents[$.inArray(obj.id, m[obj.children_d[i]].parents)] = id; + } + i = $.inArray(obj.id, this._data.core.selected); + if(i !== -1) { this._data.core.selected[i] = id; } + // update model and obj itself (obj.id, this._model.data[KEY]) + i = this.get_node(obj.id, true); + if(i) { + i.attr('id', id); //.children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor'); + if(this.element.attr('aria-activedescendant') === obj.id) { + this.element.attr('aria-activedescendant', id); + } + } + delete m[obj.id]; + obj.id = id; + obj.li_attr.id = id; + m[id] = obj; + /** + * triggered when a node id value is changed + * @event + * @name set_id.jstree + * @param {Object} node + * @param {String} old the old id + */ + this.trigger('set_id',{ "node" : obj, "new" : obj.id, "old" : old }); + return true; + }, + /** + * get the text value of a node + * @name get_text(obj) + * @param {mixed} obj the node + * @return {String} + */ + get_text : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === $.jstree.root) ? false : obj.text; + }, + /** + * set the text value of a node. Used internally, please use `rename_node(obj, val)`. + * @private + * @name set_text(obj, val) + * @param {mixed} obj the node, you can pass an array to set the text on multiple nodes + * @param {String} val the new text value + * @return {Boolean} + * @trigger set_text.jstree + */ + set_text : function (obj, val) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_text(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + obj.text = val; + if(this.get_node(obj, true).length) { + this.redraw_node(obj.id); + } + /** + * triggered when a node text value is changed + * @event + * @name set_text.jstree + * @param {Object} obj + * @param {String} text the new value + */ + this.trigger('set_text',{ "obj" : obj, "text" : val }); + return true; + }, + /** + * gets a JSON representation of a node (or the whole tree) + * @name get_json([obj, options]) + * @param {mixed} obj + * @param {Object} options + * @param {Boolean} options.no_state do not return state information + * @param {Boolean} options.no_id do not return ID + * @param {Boolean} options.no_children do not include children + * @param {Boolean} options.no_data do not include node data + * @param {Boolean} options.no_li_attr do not include LI attributes + * @param {Boolean} options.no_a_attr do not include A attributes + * @param {Boolean} options.flat return flat JSON instead of nested + * @return {Object} + */ + get_json : function (obj, options, flat) { + obj = this.get_node(obj || $.jstree.root); + if(!obj) { return false; } + if(options && options.flat && !flat) { flat = []; } + var tmp = { + 'id' : obj.id, + 'text' : obj.text, + 'icon' : this.get_icon(obj), + 'li_attr' : $.extend(true, {}, obj.li_attr), + 'a_attr' : $.extend(true, {}, obj.a_attr), + 'state' : {}, + 'data' : options && options.no_data ? false : $.extend(true, {}, obj.data) + //( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ), + }, i, j; + if(options && options.flat) { + tmp.parent = obj.parent; + } + else { + tmp.children = []; + } + if(!options || !options.no_state) { + for(i in obj.state) { + if(obj.state.hasOwnProperty(i)) { + tmp.state[i] = obj.state[i]; + } + } + } else { + delete tmp.state; + } + if(options && options.no_li_attr) { + delete tmp.li_attr; + } + if(options && options.no_a_attr) { + delete tmp.a_attr; + } + if(options && options.no_id) { + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + if(tmp.a_attr && tmp.a_attr.id) { + delete tmp.a_attr.id; + } + } + if(options && options.flat && obj.id !== $.jstree.root) { + flat.push(tmp); + } + if(!options || !options.no_children) { + for(i = 0, j = obj.children.length; i < j; i++) { + if(options && options.flat) { + this.get_json(obj.children[i], options, flat); + } + else { + tmp.children.push(this.get_json(obj.children[i], options)); + } + } + } + return options && options.flat ? flat : (obj.id === $.jstree.root ? tmp.children : tmp); + }, + /** + * create a new node (do not confuse with load_node) + * @name create_node([par, node, pos, callback, is_loaded]) + * @param {mixed} par the parent node (to create a root node use either "#" (string) or `null`) + * @param {mixed} node the data for the new node (a valid JSON object, or a simple string with the name) + * @param {mixed} pos the index at which to insert the node, "first" and "last" are also supported, default is "last" + * @param {Function} callback a function to be called once the node is created + * @param {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded + * @return {String} the ID of the newly create node + * @trigger model.jstree, create_node.jstree + */ + create_node : function (par, node, pos, callback, is_loaded) { + if(par === null) { par = $.jstree.root; } + par = this.get_node(par); + if(!par) { return false; } + pos = pos === undefined ? "last" : pos; + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.create_node(par, node, pos, callback, true); }); + } + if(!node) { node = { "text" : this.get_string('New node') }; } + if(typeof node === "string") { node = { "text" : node }; } + if(node.text === undefined) { node.text = this.get_string('New node'); } + var tmp, dpc, i, j; + + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children); + par = tmp; + break; + case "after" : + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children) + 1; + par = tmp; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > par.children.length) { pos = par.children.length; } + if(!node.id) { node.id = true; } + if(!this.check("create_node", node, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, par.id, par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : par.id }); + + par.children_d = par.children_d.concat(dpc); + for(i = 0, j = par.parents.length; i < j; i++) { + this._model.data[par.parents[i]].children_d = this._model.data[par.parents[i]].children_d.concat(dpc); + } + node = tmp; + tmp = []; + for(i = 0, j = par.children.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = par.children[i]; + } + tmp[pos] = node.id; + par.children = tmp; + + this.redraw_node(par, true); + if(callback) { callback.call(this, this.get_node(node)); } + /** + * triggered when a node is created + * @event + * @name create_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the new node among the parent's children + */ + this.trigger('create_node', { "node" : this.get_node(node), "parent" : par.id, "position" : pos }); + return node.id; + }, + /** + * set the text value of a node + * @name rename_node(obj, val) + * @param {mixed} obj the node, you can pass an array to rename multiple nodes to the same name + * @param {String} val the new text value + * @return {Boolean} + * @trigger rename_node.jstree + */ + rename_node : function (obj, val) { + var t1, t2, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.rename_node(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + old = obj.text; + if(!this.check("rename_node", obj, this.get_parent(obj), val)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + this.set_text(obj, val); // .apply(this, Array.prototype.slice.call(arguments)) + /** + * triggered when a node is renamed + * @event + * @name rename_node.jstree + * @param {Object} node + * @param {String} text the new value + * @param {String} old the old value + */ + this.trigger('rename_node', { "node" : obj, "text" : val, "old" : old }); + return true; + }, + /** + * remove a node + * @name delete_node(obj) + * @param {mixed} obj the node, you can pass an array to delete multiple nodes + * @return {Boolean} + * @trigger delete_node.jstree, changed.jstree + */ + delete_node : function (obj) { + var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.delete_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + par = this.get_node(obj.parent); + pos = $.inArray(obj.id, par.children); + c = false; + if(!this.check("delete_node", obj, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(pos !== -1) { + par.children = $.vakata.array_remove(par.children, pos); + } + tmp = obj.children_d.concat([]); + tmp.push(obj.id); + for(i = 0, j = obj.parents.length; i < j; i++) { + this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) { + return $.inArray(v, tmp) === -1; + }); + } + for(k = 0, l = tmp.length; k < l; k++) { + if(this._model.data[tmp[k]].state.selected) { + c = true; + break; + } + } + if (c) { + this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) { + return $.inArray(v, tmp) === -1; + }); + } + /** + * triggered when a node is deleted + * @event + * @name delete_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + */ + this.trigger('delete_node', { "node" : obj, "parent" : par.id }); + if(c) { + this.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id }); + } + for(k = 0, l = tmp.length; k < l; k++) { + delete this._model.data[tmp[k]]; + } + if($.inArray(this._data.core.focused, tmp) !== -1) { + this._data.core.focused = null; + top = this.element[0].scrollTop; + lft = this.element[0].scrollLeft; + if(par.id === $.jstree.root) { + if (this._model.data[$.jstree.root].children[0]) { + this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus(); + } + } + else { + this.get_node(par, true).children('.jstree-anchor').focus(); + } + this.element[0].scrollTop = top; + this.element[0].scrollLeft = lft; + } + this.redraw_node(par, true); + return true; + }, + /** + * check if an operation is premitted on the tree. Used internally. + * @private + * @name check(chk, obj, par, pos) + * @param {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node" + * @param {mixed} obj the node + * @param {mixed} par the parent + * @param {mixed} pos the position to insert at, or if "rename_node" - the new name + * @param {mixed} more some various additional information, for example if a "move_node" operations is triggered by DND this will be the hovered node + * @return {Boolean} + */ + check : function (chk, obj, par, pos, more) { + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj, + chc = this.settings.core.check_callback; + if(chk === "move_node" || chk === "copy_node") { + if((!more || !more.is_multi) && (obj.id === par.id || (chk === "move_node" && $.inArray(obj.id, par.children) === pos) || $.inArray(par.id, obj.children_d) !== -1)) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + } + if(tmp && tmp.data) { tmp = tmp.data; } + if(tmp && tmp.functions && (tmp.functions[chk] === false || tmp.functions[chk] === true)) { + if(tmp.functions[chk] === false) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_02', 'reason' : 'Node data prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return tmp.functions[chk]; + } + if(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + return true; + }, + /** + * get the last error + * @name last_error() + * @return {Object} + */ + last_error : function () { + return this._data.core.last_error; + }, + /** + * move a node to a new parent + * @name move_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to move, pass an array to move multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} is_loaded internal parameter indicating if the parent node has been loaded + * @param {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn + * @param {Boolean} instance internal parameter indicating if the node comes from another instance + * @trigger move_node.jstree + */ + move_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) { + var t1, t2, old_par, old_pos, new_par, old_ins, is_multi, dpc, tmp, i, j, k, l, p; + + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + if(!par) { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.move_node(obj, par, pos, callback, true, false, origin); }); + } + + if($.isArray(obj)) { + if(obj.length === 1) { + obj = obj[0]; + } + else { + //obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + if((tmp = this.move_node(obj[t1], par, pos, callback, is_loaded, false, origin))) { + par = tmp; + pos = "after"; + } + } + this.redraw(); + return true; + } + } + obj = obj && obj.id ? obj : this.get_node(obj); + + if(!obj || obj.id === $.jstree.root) { return false; } + + old_par = (obj.parent || $.jstree.root).toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent); + old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id)); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + old_pos = old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1; + if(old_ins && old_ins._id) { + obj = old_ins._model.data[obj.id]; + } + + if(is_multi) { + if((tmp = this.copy_node(obj, par, pos, callback, is_loaded, false, origin))) { + if(old_ins) { old_ins.delete_node(obj); } + return tmp; + } + return false; + } + //var m = this._model.data; + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("move_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(obj.parent === new_par.id) { + dpc = new_par.children.concat(); + tmp = $.inArray(obj.id, dpc); + if(tmp !== -1) { + dpc = $.vakata.array_remove(dpc, tmp); + if(pos > tmp) { pos--; } + } + tmp = []; + for(i = 0, j = dpc.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = dpc[i]; + } + tmp[pos] = obj.id; + new_par.children = tmp; + this._node_changed(new_par.id); + this.redraw(new_par.id === $.jstree.root); + } + else { + // clean old parent and up + tmp = obj.children_d.concat(); + tmp.push(obj.id); + for(i = 0, j = obj.parents.length; i < j; i++) { + dpc = []; + p = old_ins._model.data[obj.parents[i]].children_d; + for(k = 0, l = p.length; k < l; k++) { + if($.inArray(p[k], tmp) === -1) { + dpc.push(p[k]); + } + } + old_ins._model.data[obj.parents[i]].children_d = dpc; + } + old_ins._model.data[old_par].children = $.vakata.array_remove_item(old_ins._model.data[old_par].children, obj.id); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(tmp); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = obj.id; + new_par.children = dpc; + new_par.children_d.push(obj.id); + new_par.children_d = new_par.children_d.concat(obj.children_d); + + // update object + obj.parent = new_par.id; + tmp = new_par.parents.concat(); + tmp.unshift(new_par.id); + p = obj.parents.length; + obj.parents = tmp; + + // update object children + tmp = tmp.concat(); + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1); + Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp); + } + + if(old_par === $.jstree.root || new_par.id === $.jstree.root) { + this._model.force_full_redraw = true; + } + if(!this._model.force_full_redraw) { + this._node_changed(old_par); + this._node_changed(new_par.id); + } + if(!skip_redraw) { + this.redraw(); + } + } + if(callback) { callback.call(this, obj, new_par, pos); } + /** + * triggered when a node is moved + * @event + * @name move_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Number} old_position the old position of the node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('move_node', { "node" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_pos, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this }); + return obj.id; + }, + /** + * copy a node to a new parent + * @name copy_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to copy, pass an array to copy multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} is_loaded internal parameter indicating if the parent node has been loaded + * @param {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn + * @param {Boolean} instance internal parameter indicating if the node comes from another instance + * @trigger model.jstree copy_node.jstree + */ + copy_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) { + var t1, t2, dpc, tmp, i, j, node, old_par, new_par, old_ins, is_multi; + + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + if(!par) { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true, false, origin); }); + } + + if($.isArray(obj)) { + if(obj.length === 1) { + obj = obj[0]; + } + else { + //obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + if((tmp = this.copy_node(obj[t1], par, pos, callback, is_loaded, true, origin))) { + par = tmp; + pos = "after"; + } + } + this.redraw(); + return true; + } + } + obj = obj && obj.id ? obj : this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + + old_par = (obj.parent || $.jstree.root).toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent); + old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id)); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + + if(old_ins && old_ins._id) { + obj = old_ins._model.data[obj.id]; + } + + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("copy_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + node = old_ins ? old_ins.get_json(obj, { no_id : true, no_data : true, no_state : true }) : obj; + if(!node) { return false; } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, new_par.id, new_par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + if(obj && obj.state && obj.state.loaded === false) { tmp.state.loaded = false; } + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : new_par.id }); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(dpc); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = tmp.id; + new_par.children = dpc; + new_par.children_d.push(tmp.id); + new_par.children_d = new_par.children_d.concat(tmp.children_d); + + if(new_par.id === $.jstree.root) { + this._model.force_full_redraw = true; + } + if(!this._model.force_full_redraw) { + this._node_changed(new_par.id); + } + if(!skip_redraw) { + this.redraw(new_par.id === $.jstree.root); + } + if(callback) { callback.call(this, tmp, new_par, pos); } + /** + * triggered when a node is copied + * @event + * @name copy_node.jstree + * @param {Object} node the copied node + * @param {Object} original the original node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Number} old_position the position of the original node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('copy_node', { "node" : tmp, "original" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1,'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this }); + return tmp.id; + }, + /** + * cut a node (a later call to `paste(obj)` would move the node) + * @name cut(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger cut.jstree + */ + cut : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'move_node'; + /** + * triggered when nodes are added to the buffer for moving + * @event + * @name cut.jstree + * @param {Array} node + */ + this.trigger('cut', { "node" : obj }); + }, + /** + * copy a node (a later call to `paste(obj)` would copy the node) + * @name copy(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger copy.jstree + */ + copy : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'copy_node'; + /** + * triggered when nodes are added to the buffer for copying + * @event + * @name copy.jstree + * @param {Array} node + */ + this.trigger('copy', { "node" : obj }); + }, + /** + * get the current buffer (any nodes that are waiting for a paste operation) + * @name get_buffer() + * @return {Object} an object consisting of `mode` ("copy_node" or "move_node"), `node` (an array of objects) and `inst` (the instance) + */ + get_buffer : function () { + return { 'mode' : ccp_mode, 'node' : ccp_node, 'inst' : ccp_inst }; + }, + /** + * check if there is something in the buffer to paste + * @name can_paste() + * @return {Boolean} + */ + can_paste : function () { + return ccp_mode !== false && ccp_node !== false; // && ccp_inst._model.data[ccp_node]; + }, + /** + * copy or move the previously cut or copied nodes to a new parent + * @name paste(obj [, pos]) + * @param {mixed} obj the new parent + * @param {mixed} pos the position to insert at (besides integer, "first" and "last" are supported), defaults to integer `0` + * @trigger paste.jstree + */ + paste : function (obj, pos) { + obj = this.get_node(obj); + if(!obj || !ccp_mode || !ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; } + if(this[ccp_mode](ccp_node, obj, pos, false, false, false, ccp_inst)) { + /** + * triggered when paste is invoked + * @event + * @name paste.jstree + * @param {String} parent the ID of the receiving node + * @param {Array} node the nodes in the buffer + * @param {String} mode the performed operation - "copy_node" or "move_node" + */ + this.trigger('paste', { "parent" : obj.id, "node" : ccp_node, "mode" : ccp_mode }); + } + ccp_node = false; + ccp_mode = false; + ccp_inst = false; + }, + /** + * clear the buffer of previously copied or cut nodes + * @name clear_buffer() + * @trigger clear_buffer.jstree + */ + clear_buffer : function () { + ccp_node = false; + ccp_mode = false; + ccp_inst = false; + /** + * triggered when the copy / cut buffer is cleared + * @event + * @name clear_buffer.jstree + */ + this.trigger('clear_buffer'); + }, + /** + * put a node in edit mode (input field to rename the node) + * @name edit(obj [, default_text, callback]) + * @param {mixed} obj + * @param {String} default_text the text to populate the input with (if omitted or set to a non-string value the node's text value is used) + * @param {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise) and a boolean indicating if the user cancelled the edit. You can access the node's title using .text + */ + edit : function (obj, default_text, callback) { + var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false; + obj = this.get_node(obj); + if(!obj) { return false; } + if(this.settings.core.check_callback === false) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_07', 'reason' : 'Could not edit node because of check_callback' }; + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + tmp = obj; + default_text = typeof default_text === 'string' ? default_text : obj.text; + this.set_text(obj, ""); + obj = this._open_to(obj); + tmp.text = default_text; + + rtl = this._data.core.rtl; + w = this.element.width(); + this._data.core.focused = tmp.id; + a = obj.children('.jstree-anchor').focus(); + s = $('<span>'); + /*! + oi = obj.children("i:visible"), + ai = a.children("i:visible"), + w1 = oi.width() * oi.length, + w2 = ai.width() * ai.length, + */ + t = default_text; + h1 = $("<"+"div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"); + h2 = $("<"+"input />", { + "value" : t, + "class" : "jstree-rename-input", + // "size" : t.length, + "css" : { + "padding" : "0", + "border" : "1px solid silver", + "box-sizing" : "border-box", + "display" : "inline-block", + "height" : (this._data.core.li_height) + "px", + "lineHeight" : (this._data.core.li_height) + "px", + "width" : "150px" // will be set a bit further down + }, + "blur" : $.proxy(function (e) { + e.stopImmediatePropagation(); + e.preventDefault(); + var i = s.children(".jstree-rename-input"), + v = i.val(), + f = this.settings.core.force_text, + nv; + if(v === "") { v = t; } + h1.remove(); + s.replaceWith(a); + s.remove(); + t = f ? t : $('<div></div>').append($.parseHTML(t)).html(); + this.set_text(obj, t); + nv = !!this.rename_node(obj, f ? $('<div></div>').text(v).text() : $('<div></div>').append($.parseHTML(v)).html()); + if(!nv) { + this.set_text(obj, t); // move this up? and fix #483 + } + this._data.core.focused = tmp.id; + setTimeout($.proxy(function () { + var node = this.get_node(tmp.id, true); + if(node.length) { + this._data.core.focused = tmp.id; + node.children('.jstree-anchor').focus(); + } + }, this), 0); + if(callback) { + callback.call(this, tmp, nv, cancel); + } + h2 = null; + }, this), + "keydown" : function (e) { + var key = e.which; + if(key === 27) { + cancel = true; + this.value = t; + } + if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) { + e.stopImmediatePropagation(); + } + if(key === 27 || key === 13) { + e.preventDefault(); + this.blur(); + } + }, + "click" : function (e) { e.stopImmediatePropagation(); }, + "mousedown" : function (e) { e.stopImmediatePropagation(); }, + "keyup" : function (e) { + h2.width(Math.min(h1.text("pW" + this.value).width(),w)); + }, + "keypress" : function(e) { + if(e.which === 13) { return false; } + } + }); + fn = { + fontFamily : a.css('fontFamily') || '', + fontSize : a.css('fontSize') || '', + fontWeight : a.css('fontWeight') || '', + fontStyle : a.css('fontStyle') || '', + fontStretch : a.css('fontStretch') || '', + fontVariant : a.css('fontVariant') || '', + letterSpacing : a.css('letterSpacing') || '', + wordSpacing : a.css('wordSpacing') || '' + }; + s.attr('class', a.attr('class')).append(a.contents().clone()).append(h2); + a.replaceWith(s); + h1.css(fn); + h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select(); + $(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) { + if (h2 && e.target !== h2) { + $(h2).blur(); + } + }); + }, + + + /** + * changes the theme + * @name set_theme(theme_name [, theme_url]) + * @param {String} theme_name the name of the new theme to apply + * @param {mixed} theme_url the location of the CSS file for this theme. Omit or set to `false` if you manually included the file. Set to `true` to autoload from the `core.themes.dir` directory. + * @trigger set_theme.jstree + */ + set_theme : function (theme_name, theme_url) { + if(!theme_name) { return false; } + if(theme_url === true) { + var dir = this.settings.core.themes.dir; + if(!dir) { dir = $.jstree.path + '/themes'; } + theme_url = dir + '/' + theme_name + '/style.css'; + } + if(theme_url && $.inArray(theme_url, themes_loaded) === -1) { + $('head').append('<'+'link rel="stylesheet" href="' + theme_url + '" type="text/css" />'); + themes_loaded.push(theme_url); + } + if(this._data.core.themes.name) { + this.element.removeClass('jstree-' + this._data.core.themes.name); + } + this._data.core.themes.name = theme_name; + this.element.addClass('jstree-' + theme_name); + this.element[this.settings.core.themes.responsive ? 'addClass' : 'removeClass' ]('jstree-' + theme_name + '-responsive'); + /** + * triggered when a theme is set + * @event + * @name set_theme.jstree + * @param {String} theme the new theme + */ + this.trigger('set_theme', { 'theme' : theme_name }); + }, + /** + * gets the name of the currently applied theme name + * @name get_theme() + * @return {String} + */ + get_theme : function () { return this._data.core.themes.name; }, + /** + * changes the theme variant (if the theme has variants) + * @name set_theme_variant(variant_name) + * @param {String|Boolean} variant_name the variant to apply (if `false` is used the current variant is removed) + */ + set_theme_variant : function (variant_name) { + if(this._data.core.themes.variant) { + this.element.removeClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + this._data.core.themes.variant = variant_name; + if(variant_name) { + this.element.addClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + }, + /** + * gets the name of the currently applied theme variant + * @name get_theme() + * @return {String} + */ + get_theme_variant : function () { return this._data.core.themes.variant; }, + /** + * shows a striped background on the container (if the theme supports it) + * @name show_stripes() + */ + show_stripes : function () { + this._data.core.themes.stripes = true; + this.get_container_ul().addClass("jstree-striped"); + /** + * triggered when stripes are shown + * @event + * @name show_stripes.jstree + */ + this.trigger('show_stripes'); + }, + /** + * hides the striped background on the container + * @name hide_stripes() + */ + hide_stripes : function () { + this._data.core.themes.stripes = false; + this.get_container_ul().removeClass("jstree-striped"); + /** + * triggered when stripes are hidden + * @event + * @name hide_stripes.jstree + */ + this.trigger('hide_stripes'); + }, + /** + * toggles the striped background on the container + * @name toggle_stripes() + */ + toggle_stripes : function () { if(this._data.core.themes.stripes) { this.hide_stripes(); } else { this.show_stripes(); } }, + /** + * shows the connecting dots (if the theme supports it) + * @name show_dots() + */ + show_dots : function () { + this._data.core.themes.dots = true; + this.get_container_ul().removeClass("jstree-no-dots"); + /** + * triggered when dots are shown + * @event + * @name show_dots.jstree + */ + this.trigger('show_dots'); + }, + /** + * hides the connecting dots + * @name hide_dots() + */ + hide_dots : function () { + this._data.core.themes.dots = false; + this.get_container_ul().addClass("jstree-no-dots"); + /** + * triggered when dots are hidden + * @event + * @name hide_dots.jstree + */ + this.trigger('hide_dots'); + }, + /** + * toggles the connecting dots + * @name toggle_dots() + */ + toggle_dots : function () { if(this._data.core.themes.dots) { this.hide_dots(); } else { this.show_dots(); } }, + /** + * show the node icons + * @name show_icons() + */ + show_icons : function () { + this._data.core.themes.icons = true; + this.get_container_ul().removeClass("jstree-no-icons"); + /** + * triggered when icons are shown + * @event + * @name show_icons.jstree + */ + this.trigger('show_icons'); + }, + /** + * hide the node icons + * @name hide_icons() + */ + hide_icons : function () { + this._data.core.themes.icons = false; + this.get_container_ul().addClass("jstree-no-icons"); + /** + * triggered when icons are hidden + * @event + * @name hide_icons.jstree + */ + this.trigger('hide_icons'); + }, + /** + * toggle the node icons + * @name toggle_icons() + */ + toggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }, + /** + * show the node ellipsis + * @name show_icons() + */ + show_ellipsis : function () { + this._data.core.themes.ellipsis = true; + this.get_container_ul().addClass("jstree-ellipsis"); + /** + * triggered when ellisis is shown + * @event + * @name show_ellipsis.jstree + */ + this.trigger('show_ellipsis'); + }, + /** + * hide the node ellipsis + * @name hide_ellipsis() + */ + hide_ellipsis : function () { + this._data.core.themes.ellipsis = false; + this.get_container_ul().removeClass("jstree-ellipsis"); + /** + * triggered when ellisis is hidden + * @event + * @name hide_ellipsis.jstree + */ + this.trigger('hide_ellipsis'); + }, + /** + * toggle the node ellipsis + * @name toggle_icons() + */ + toggle_ellipsis : function () { if(this._data.core.themes.ellipsis) { this.hide_ellipsis(); } else { this.show_ellipsis(); } }, + /** + * set the node icon for a node + * @name set_icon(obj, icon) + * @param {mixed} obj + * @param {String} icon the new icon - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + */ + set_icon : function (obj, icon) { + var t1, t2, dom, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_icon(obj[t1], icon); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + old = obj.icon; + obj.icon = icon === true || icon === null || icon === undefined || icon === '' ? true : icon; + dom = this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon"); + if(icon === false) { + this.hide_icon(obj); + } + else if(icon === true || icon === null || icon === undefined || icon === '') { + dom.removeClass('jstree-themeicon-custom ' + old).css("background","").removeAttr("rel"); + if(old === false) { this.show_icon(obj); } + } + else if(icon.indexOf("/") === -1 && icon.indexOf(".") === -1) { + dom.removeClass(old).css("background",""); + dom.addClass(icon + ' jstree-themeicon-custom').attr("rel",icon); + if(old === false) { this.show_icon(obj); } + } + else { + dom.removeClass(old).css("background",""); + dom.addClass('jstree-themeicon-custom').css("background", "url('" + icon + "') center center no-repeat").attr("rel",icon); + if(old === false) { this.show_icon(obj); } + } + return true; + }, + /** + * get the node icon for a node + * @name get_icon(obj) + * @param {mixed} obj + * @return {String} + */ + get_icon : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === $.jstree.root) ? false : obj.icon; + }, + /** + * hide the icon on an individual node + * @name hide_icon(obj) + * @param {mixed} obj + */ + hide_icon : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.hide_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === $.jstree.root) { return false; } + obj.icon = false; + this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon").addClass('jstree-themeicon-hidden'); + return true; + }, + /** + * show the icon on an individual node + * @name show_icon(obj) + * @param {mixed} obj + */ + show_icon : function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.show_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === $.jstree.root) { return false; } + dom = this.get_node(obj, true); + obj.icon = dom.length ? dom.children(".jstree-anchor").children(".jstree-themeicon").attr('rel') : true; + if(!obj.icon) { obj.icon = true; } + dom.children(".jstree-anchor").children(".jstree-themeicon").removeClass('jstree-themeicon-hidden'); + return true; + } + }; + + // helpers + $.vakata = {}; + // collect attributes + $.vakata.attributes = function(node, with_values) { + node = $(node)[0]; + var attr = with_values ? {} : []; + if(node && node.attributes) { + $.each(node.attributes, function (i, v) { + if($.inArray(v.name.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; } + if(v.value !== null && $.trim(v.value) !== '') { + if(with_values) { attr[v.name] = v.value; } + else { attr.push(v.name); } + } + }); + } + return attr; + }; + $.vakata.array_unique = function(array) { + var a = [], i, j, l, o = {}; + for(i = 0, l = array.length; i < l; i++) { + if(o[array[i]] === undefined) { + a.push(array[i]); + o[array[i]] = true; + } + } + return a; + }; + // remove item from array + $.vakata.array_remove = function(array, from) { + array.splice(from, 1); + return array; + //var rest = array.slice((to || from) + 1 || array.length); + //array.length = from < 0 ? array.length + from : from; + //array.push.apply(array, rest); + //return array; + }; + // remove item from array + $.vakata.array_remove_item = function(array, item) { + var tmp = $.inArray(item, array); + return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array; + }; + $.vakata.array_filter = function(c,a,b,d,e) { + if (c.filter) { + return c.filter(a, b); + } + d=[]; + for (e in c) { + if (~~e+''===e+'' && e>=0 && a.call(b,c[e],+e,c)) { + d.push(c[e]); + } + } + return d; + }; + + +/** + * ### Changed plugin + * + * This plugin adds more information to the `changed.jstree` event. The new data is contained in the `changed` event data property, and contains a lists of `selected` and `deselected` nodes. + */ + + $.jstree.plugins.changed = function (options, parent) { + var last = []; + this.trigger = function (ev, data) { + var i, j; + if(!data) { + data = {}; + } + if(ev.replace('.jstree','') === 'changed') { + data.changed = { selected : [], deselected : [] }; + var tmp = {}; + for(i = 0, j = last.length; i < j; i++) { + tmp[last[i]] = 1; + } + for(i = 0, j = data.selected.length; i < j; i++) { + if(!tmp[data.selected[i]]) { + data.changed.selected.push(data.selected[i]); + } + else { + tmp[data.selected[i]] = 2; + } + } + for(i = 0, j = last.length; i < j; i++) { + if(tmp[last[i]] === 1) { + data.changed.deselected.push(last[i]); + } + } + last = data.selected.slice(); + } + /** + * triggered when selection changes (the "changed" plugin enhances the original event with more data) + * @event + * @name changed.jstree + * @param {Object} node + * @param {Object} action the action that caused the selection to change + * @param {Array} selected the current selection + * @param {Object} changed an object containing two properties `selected` and `deselected` - both arrays of node IDs, which were selected or deselected since the last changed event + * @param {Object} event the event (if any) that triggered this changed event + * @plugin changed + */ + parent.trigger.call(this, ev, data); + }; + this.refresh = function (skip_loading, forget_state) { + last = []; + return parent.refresh.apply(this, arguments); + }; + }; + +/** + * ### Checkbox plugin + * + * This plugin renders checkbox icons in front of each node, making multiple selection much easier. + * It also supports tri-state behavior, meaning that if a node has a few of its children checked it will be rendered as undetermined, and state will be propagated up. + */ + + var _i = document.createElement('I'); + _i.className = 'jstree-icon jstree-checkbox'; + _i.setAttribute('role', 'presentation'); + /** + * stores all defaults for the checkbox plugin + * @name $.jstree.defaults.checkbox + * @plugin checkbox + */ + $.jstree.defaults.checkbox = { + /** + * a boolean indicating if checkboxes should be visible (can be changed at a later time using `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`. + * @name $.jstree.defaults.checkbox.visible + * @plugin checkbox + */ + visible : true, + /** + * a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to `true`. + * @name $.jstree.defaults.checkbox.three_state + * @plugin checkbox + */ + three_state : true, + /** + * a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`. + * @name $.jstree.defaults.checkbox.whole_node + * @plugin checkbox + */ + whole_node : true, + /** + * a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`. + * @name $.jstree.defaults.checkbox.keep_selected_style + * @plugin checkbox + */ + keep_selected_style : true, + /** + * This setting controls how cascading and undetermined nodes are applied. + * If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled, if 'undetermined' is in the string - undetermined nodes will be used. + * If `three_state` is set to `true` this setting is automatically set to 'up+down+undetermined'. Defaults to ''. + * @name $.jstree.defaults.checkbox.cascade + * @plugin checkbox + */ + cascade : '', + /** + * This setting controls if checkbox are bound to the general tree selection or to an internal array maintained by the checkbox plugin. Defaults to `true`, only set to `false` if you know exactly what you are doing. + * @name $.jstree.defaults.checkbox.tie_selection + * @plugin checkbox + */ + tie_selection : true + }; + $.jstree.plugins.checkbox = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this._data.checkbox.uto = false; + this._data.checkbox.selected = []; + if(this.settings.checkbox.three_state) { + this.settings.checkbox.cascade = 'up+down+undetermined'; + } + this.element + .on("init.jstree", $.proxy(function () { + this._data.checkbox.visible = this.settings.checkbox.visible; + if(!this.settings.checkbox.keep_selected_style) { + this.element.addClass('jstree-checkbox-no-clicked'); + } + if(this.settings.checkbox.tie_selection) { + this.element.addClass('jstree-checkbox-selection'); + } + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ](); + }, this)); + if(this.settings.checkbox.cascade.indexOf('undetermined') !== -1) { + this.element + .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () { + // only if undetermined is in setting + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + }, this)); + } + if(!this.settings.checkbox.tie_selection) { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + p = m[data.parent], + dpc = data.nodes, + i, j; + for(i = 0, j = dpc.length; i < j; i++) { + m[dpc[i]].state.checked = m[dpc[i]].state.checked || (m[dpc[i]].original && m[dpc[i]].original.state && m[dpc[i]].original.state.checked); + if(m[dpc[i]].state.checked) { + this._data.checkbox.selected.push(dpc[i]); + } + } + }, this)); + } + if(this.settings.checkbox.cascade.indexOf('up') !== -1 || this.settings.checkbox.cascade.indexOf('down') !== -1) { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + p = m[data.parent], + dpc = data.nodes, + chd = [], + c, i, j, k, l, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection; + + if(s.indexOf('down') !== -1) { + // apply down + if(p.state[ t ? 'selected' : 'checked' ]) { + for(i = 0, j = dpc.length; i < j; i++) { + m[dpc[i]].state[ t ? 'selected' : 'checked' ] = true; + } + this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(dpc); + } + else { + for(i = 0, j = dpc.length; i < j; i++) { + if(m[dpc[i]].state[ t ? 'selected' : 'checked' ]) { + for(k = 0, l = m[dpc[i]].children_d.length; k < l; k++) { + m[m[dpc[i]].children_d[k]].state[ t ? 'selected' : 'checked' ] = true; + } + this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(m[dpc[i]].children_d); + } + } + } + } + + if(s.indexOf('up') !== -1) { + // apply up + for(i = 0, j = p.children_d.length; i < j; i++) { + if(!m[p.children_d[i]].children.length) { + chd.push(m[p.children_d[i]].parent); + } + } + chd = $.vakata.array_unique(chd); + for(k = 0, l = chd.length; k < l; k++) { + p = m[chd[k]]; + while(p && p.id !== $.jstree.root) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass( t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + } + + this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected); + }, this)) + .on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + m = this._model.data, + par = this.get_node(obj.parent), + dom = this.get_node(obj, true), + i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection, + sel = {}, cur = this._data[ t ? 'core' : 'checkbox' ].selected; + + for (i = 0, j = cur.length; i < j; i++) { + sel[cur[i]] = true; + } + // apply down + if(s.indexOf('down') !== -1) { + //this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d)); + for(i = 0, j = obj.children_d.length; i < j; i++) { + sel[obj.children_d[i]] = true; + tmp = m[obj.children_d[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = true; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + } + + // apply up + if(s.indexOf('up') !== -1) { + while(par && par.id !== $.jstree.root) { + c = 0; + for(i = 0, j = par.children.length; i < j; i++) { + c += m[par.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + par.state[ t ? 'selected' : 'checked' ] = true; + sel[par.id] = true; + //this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id); + tmp = this.get_node(par, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + par = this.get_node(par.parent); + } + } + + cur = []; + for (i in sel) { + if (sel.hasOwnProperty(i)) { + cur.push(i); + } + } + this._data[ t ? 'core' : 'checkbox' ].selected = cur; + + // apply down (process .children separately?) + if(s.indexOf('down') !== -1 && dom.length) { + dom.find('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', true); + } + }, this)) + .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) { + var obj = this.get_node($.jstree.root), + m = this._model.data, + i, j, tmp; + for(i = 0, j = obj.children_d.length; i < j; i++) { + tmp = m[obj.children_d[i]]; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + }, this)) + .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + dom = this.get_node(obj, true), + i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection, + cur = this._data[ t ? 'core' : 'checkbox' ].selected, sel = {}; + if(obj && obj.original && obj.original.state && obj.original.state.undetermined) { + obj.original.state.undetermined = false; + } + + // apply down + if(s.indexOf('down') !== -1) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + tmp = this._model.data[obj.children_d[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = false; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + } + + // apply up + if(s.indexOf('up') !== -1) { + for(i = 0, j = obj.parents.length; i < j; i++) { + tmp = this._model.data[obj.parents[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = false; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + tmp = this.get_node(obj.parents[i], true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + } + sel = {}; + for(i = 0, j = cur.length; i < j; i++) { + // apply down + apply up + if( + (s.indexOf('down') === -1 || $.inArray(cur[i], obj.children_d) === -1) && + (s.indexOf('up') === -1 || $.inArray(cur[i], obj.parents) === -1) + ) { + sel[cur[i]] = true; + } + } + cur = []; + for (i in sel) { + if (sel.hasOwnProperty(i)) { + cur.push(i); + } + } + this._data[ t ? 'core' : 'checkbox' ].selected = cur; + + // apply down (process .children separately?) + if(s.indexOf('down') !== -1 && dom.length) { + dom.find('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', false); + } + }, this)); + } + if(this.settings.checkbox.cascade.indexOf('up') !== -1) { + this.element + .on('delete_node.jstree', $.proxy(function (e, data) { + // apply up (whole handler) + var p = this.get_node(data.parent), + m = this._model.data, + i, j, c, tmp, t = this.settings.checkbox.tie_selection; + while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(j > 0 && c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + }, this)) + .on('move_node.jstree', $.proxy(function (e, data) { + // apply up (whole handler) + var is_multi = data.is_multi, + old_par = data.old_parent, + new_par = this.get_node(data.parent), + m = this._model.data, + p, c, i, j, tmp, t = this.settings.checkbox.tie_selection; + if(!is_multi) { + p = this.get_node(old_par); + while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(j > 0 && c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + p = new_par; + while(p && p.id !== $.jstree.root) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + if(!p.state[ t ? 'selected' : 'checked' ]) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + } + else { + if(p.state[ t ? 'selected' : 'checked' ]) { + p.state[ t ? 'selected' : 'checked' ] = false; + this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_remove_item(this._data[ t ? 'core' : 'checkbox' ].selected, p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + } + p = this.get_node(p.parent); + } + }, this)); + } + }; + /** + * set the undetermined state where and if necessary. Used internally. + * @private + * @name _undetermined() + * @plugin checkbox + */ + this._undetermined = function () { + if(this.element === null) { return; } + var i, j, k, l, o = {}, m = this._model.data, t = this.settings.checkbox.tie_selection, s = this._data[ t ? 'core' : 'checkbox' ].selected, p = [], tt = this; + for(i = 0, j = s.length; i < j; i++) { + if(m[s[i]] && m[s[i]].parents) { + for(k = 0, l = m[s[i]].parents.length; k < l; k++) { + if(o[m[s[i]].parents[k]] !== undefined) { + break; + } + if(m[s[i]].parents[k] !== $.jstree.root) { + o[m[s[i]].parents[k]] = true; + p.push(m[s[i]].parents[k]); + } + } + } + } + // attempt for server side undetermined state + this.element.find('.jstree-closed').not(':has(.jstree-children)') + .each(function () { + var tmp = tt.get_node(this), tmp2; + if(!tmp.state.loaded) { + if(tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) { + if(o[tmp.id] === undefined && tmp.id !== $.jstree.root) { + o[tmp.id] = true; + p.push(tmp.id); + } + for(k = 0, l = tmp.parents.length; k < l; k++) { + if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) { + o[tmp.parents[k]] = true; + p.push(tmp.parents[k]); + } + } + } + } + else { + for(i = 0, j = tmp.children_d.length; i < j; i++) { + tmp2 = m[tmp.children_d[i]]; + if(!tmp2.state.loaded && tmp2.original && tmp2.original.state && tmp2.original.state.undetermined && tmp2.original.state.undetermined === true) { + if(o[tmp2.id] === undefined && tmp2.id !== $.jstree.root) { + o[tmp2.id] = true; + p.push(tmp2.id); + } + for(k = 0, l = tmp2.parents.length; k < l; k++) { + if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) { + o[tmp2.parents[k]] = true; + p.push(tmp2.parents[k]); + } + } + } + } + } + }); + + this.element.find('.jstree-undetermined').removeClass('jstree-undetermined'); + for(i = 0, j = p.length; i < j; i++) { + if(!m[p[i]].state[ t ? 'selected' : 'checked' ]) { + s = this.get_node(p[i], true); + if(s && s.length) { + s.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-undetermined'); + } + } + } + }; + this.redraw_node = function(obj, deep, is_callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + var i, j, tmp = null, icon = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + if(!this.settings.checkbox.tie_selection && this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; } + icon = _i.cloneNode(false); + if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += ' jstree-checkbox-disabled'; } + tmp.insertBefore(icon, tmp.childNodes[0]); + } + } + if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) { + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + } + return obj; + }; + /** + * show the node checkbox icons + * @name show_checkboxes() + * @plugin checkbox + */ + this.show_checkboxes = function () { this._data.core.themes.checkboxes = true; this.get_container_ul().removeClass("jstree-no-checkboxes"); }; + /** + * hide the node checkbox icons + * @name hide_checkboxes() + * @plugin checkbox + */ + this.hide_checkboxes = function () { this._data.core.themes.checkboxes = false; this.get_container_ul().addClass("jstree-no-checkboxes"); }; + /** + * toggle the node icons + * @name toggle_checkboxes() + * @plugin checkbox + */ + this.toggle_checkboxes = function () { if(this._data.core.themes.checkboxes) { this.hide_checkboxes(); } else { this.show_checkboxes(); } }; + /** + * checks if a node is in an undetermined state + * @name is_undetermined(obj) + * @param {mixed} obj + * @return {Boolean} + */ + this.is_undetermined = function (obj) { + obj = this.get_node(obj); + var s = this.settings.checkbox.cascade, i, j, t = this.settings.checkbox.tie_selection, d = this._data[ t ? 'core' : 'checkbox' ].selected, m = this._model.data; + if(!obj || obj.state[ t ? 'selected' : 'checked' ] === true || s.indexOf('undetermined') === -1 || (s.indexOf('down') === -1 && s.indexOf('up') === -1)) { + return false; + } + if(!obj.state.loaded && obj.original.state.undetermined === true) { + return true; + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + if($.inArray(obj.children_d[i], d) !== -1 || (!m[obj.children_d[i]].state.loaded && m[obj.children_d[i]].original.state.undetermined)) { + return true; + } + } + return false; + }; + /** + * disable a node's checkbox + * @name disable_checkbox(obj) + * @param {mixed} obj an array can be used too + * @trigger disable_checkbox.jstree + * @plugin checkbox + */ + this.disable_checkbox = function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.disable_checkbox(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.checkbox_disabled) { + obj.state.checkbox_disabled = true; + if(dom && dom.length) { + dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled'); + } + /** + * triggered when an node's checkbox is disabled + * @event + * @name disable_checkbox.jstree + * @param {Object} node + * @plugin checkbox + */ + this.trigger('disable_checkbox', { 'node' : obj }); + } + }; + /** + * enable a node's checkbox + * @name disable_checkbox(obj) + * @param {mixed} obj an array can be used too + * @trigger enable_checkbox.jstree + * @plugin checkbox + */ + this.enable_checkbox = function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.enable_checkbox(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.checkbox_disabled) { + obj.state.checkbox_disabled = false; + if(dom && dom.length) { + dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled'); + } + /** + * triggered when an node's checkbox is enabled + * @event + * @name enable_checkbox.jstree + * @param {Object} node + * @plugin checkbox + */ + this.trigger('enable_checkbox', { 'node' : obj }); + } + }; + + this.activate_node = function (obj, e) { + if($(e.target).hasClass('jstree-checkbox-disabled')) { + return false; + } + if(this.settings.checkbox.tie_selection && (this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox'))) { + e.ctrlKey = true; + } + if(this.settings.checkbox.tie_selection || (!this.settings.checkbox.whole_node && !$(e.target).hasClass('jstree-checkbox'))) { + return parent.activate_node.call(this, obj, e); + } + if(this.is_disabled(obj)) { + return false; + } + if(this.is_checked(obj)) { + this.uncheck_node(obj, e); + } + else { + this.check_node(obj, e); + } + this.trigger('activate_node', { 'node' : this.get_node(obj) }); + }; + + /** + * check a node (only if tie_selection in checkbox settings is false, otherwise select_node will be called internally) + * @name check_node(obj) + * @param {mixed} obj an array can be used to check multiple nodes + * @trigger check_node.jstree + * @plugin checkbox + */ + this.check_node = function (obj, e) { + if(this.settings.checkbox.tie_selection) { return this.select_node(obj, false, true, e); } + var dom, t1, t2, th; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.check_node(obj[t1], e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.checked) { + obj.state.checked = true; + this._data.checkbox.selected.push(obj.id); + if(dom && dom.length) { + dom.children('.jstree-anchor').addClass('jstree-checked'); + } + /** + * triggered when an node is checked (only if tie_selection in checkbox settings is false) + * @event + * @name check_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this check_node + * @plugin checkbox + */ + this.trigger('check_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e }); + } + }; + /** + * uncheck a node (only if tie_selection in checkbox settings is false, otherwise deselect_node will be called internally) + * @name uncheck_node(obj) + * @param {mixed} obj an array can be used to uncheck multiple nodes + * @trigger uncheck_node.jstree + * @plugin checkbox + */ + this.uncheck_node = function (obj, e) { + if(this.settings.checkbox.tie_selection) { return this.deselect_node(obj, false, e); } + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.uncheck_node(obj[t1], e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.checked) { + obj.state.checked = false; + this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, obj.id); + if(dom.length) { + dom.children('.jstree-anchor').removeClass('jstree-checked'); + } + /** + * triggered when an node is unchecked (only if tie_selection in checkbox settings is false) + * @event + * @name uncheck_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this uncheck_node + * @plugin checkbox + */ + this.trigger('uncheck_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e }); + } + }; + /** + * checks all nodes in the tree (only if tie_selection in checkbox settings is false, otherwise select_all will be called internally) + * @name check_all() + * @trigger check_all.jstree, changed.jstree + * @plugin checkbox + */ + this.check_all = function () { + if(this.settings.checkbox.tie_selection) { return this.select_all(); } + var tmp = this._data.checkbox.selected.concat([]), i, j; + this._data.checkbox.selected = this._model.data[$.jstree.root].children_d.concat(); + for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) { + if(this._model.data[this._data.checkbox.selected[i]]) { + this._model.data[this._data.checkbox.selected[i]].state.checked = true; + } + } + this.redraw(true); + /** + * triggered when all nodes are checked (only if tie_selection in checkbox settings is false) + * @event + * @name check_all.jstree + * @param {Array} selected the current selection + * @plugin checkbox + */ + this.trigger('check_all', { 'selected' : this._data.checkbox.selected }); + }; + /** + * uncheck all checked nodes (only if tie_selection in checkbox settings is false, otherwise deselect_all will be called internally) + * @name uncheck_all() + * @trigger uncheck_all.jstree + * @plugin checkbox + */ + this.uncheck_all = function () { + if(this.settings.checkbox.tie_selection) { return this.deselect_all(); } + var tmp = this._data.checkbox.selected.concat([]), i, j; + for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) { + if(this._model.data[this._data.checkbox.selected[i]]) { + this._model.data[this._data.checkbox.selected[i]].state.checked = false; + } + } + this._data.checkbox.selected = []; + this.element.find('.jstree-checked').removeClass('jstree-checked'); + /** + * triggered when all nodes are unchecked (only if tie_selection in checkbox settings is false) + * @event + * @name uncheck_all.jstree + * @param {Object} node the previous selection + * @param {Array} selected the current selection + * @plugin checkbox + */ + this.trigger('uncheck_all', { 'selected' : this._data.checkbox.selected, 'node' : tmp }); + }; + /** + * checks if a node is checked (if tie_selection is on in the settings this function will return the same as is_selected) + * @name is_checked(obj) + * @param {mixed} obj + * @return {Boolean} + * @plugin checkbox + */ + this.is_checked = function (obj) { + if(this.settings.checkbox.tie_selection) { return this.is_selected(obj); } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + return obj.state.checked; + }; + /** + * get an array of all checked nodes (if tie_selection is on in the settings this function will return the same as get_selected) + * @name get_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_selected(full); } + return full ? $.map(this._data.checkbox.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.checkbox.selected; + }; + /** + * get an array of all top level checked nodes (ignoring children of checked nodes) (if tie_selection is on in the settings this function will return the same as get_top_selected) + * @name get_top_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_top_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_top_selected(full); } + var tmp = this.get_checked(true), + obj = {}, i, j, k, l; + for(i = 0, j = tmp.length; i < j; i++) { + obj[tmp[i].id] = tmp[i]; + } + for(i = 0, j = tmp.length; i < j; i++) { + for(k = 0, l = tmp[i].children_d.length; k < l; k++) { + if(obj[tmp[i].children_d[k]]) { + delete obj[tmp[i].children_d[k]]; + } + } + } + tmp = []; + for(i in obj) { + if(obj.hasOwnProperty(i)) { + tmp.push(i); + } + } + return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp; + }; + /** + * get an array of all bottom level checked nodes (ignoring selected parents) (if tie_selection is on in the settings this function will return the same as get_bottom_selected) + * @name get_bottom_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_bottom_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_bottom_selected(full); } + var tmp = this.get_checked(true), + obj = [], i, j; + for(i = 0, j = tmp.length; i < j; i++) { + if(!tmp[i].children.length) { + obj.push(tmp[i].id); + } + } + return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj; + }; + this.load_node = function (obj, callback) { + var k, l, i, j, c, tmp; + if(!$.isArray(obj) && !this.settings.checkbox.tie_selection) { + tmp = this.get_node(obj); + if(tmp && tmp.state.loaded) { + for(k = 0, l = tmp.children_d.length; k < l; k++) { + if(this._model.data[tmp.children_d[k]].state.checked) { + c = true; + this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, tmp.children_d[k]); + } + } + } + } + return parent.load_node.apply(this, arguments); + }; + this.get_state = function () { + var state = parent.get_state.apply(this, arguments); + if(this.settings.checkbox.tie_selection) { return state; } + state.checkbox = this._data.checkbox.selected.slice(); + return state; + }; + this.set_state = function (state, callback) { + var res = parent.set_state.apply(this, arguments); + if(res && state.checkbox) { + if(!this.settings.checkbox.tie_selection) { + this.uncheck_all(); + var _this = this; + $.each(state.checkbox, function (i, v) { + _this.check_node(v); + }); + } + delete state.checkbox; + this.set_state(state, callback); + return false; + } + return res; + }; + this.refresh = function (skip_loading, forget_state) { + if(!this.settings.checkbox.tie_selection) { + this._data.checkbox.selected = []; + } + return parent.refresh.apply(this, arguments); + }; + }; + + // include the checkbox plugin by default + // $.jstree.defaults.plugins.push("checkbox"); + +/** + * ### Conditionalselect plugin + * + * This plugin allows defining a callback to allow or deny node selection by user input (activate node method). + */ + + /** + * a callback (function) which is invoked in the instance's scope and receives two arguments - the node and the event that triggered the `activate_node` call. Returning false prevents working with the node, returning true allows invoking activate_node. Defaults to returning `true`. + * @name $.jstree.defaults.checkbox.visible + * @plugin checkbox + */ + $.jstree.defaults.conditionalselect = function () { return true; }; + $.jstree.plugins.conditionalselect = function (options, parent) { + // own function + this.activate_node = function (obj, e) { + if(this.settings.conditionalselect.call(this, this.get_node(obj), e)) { + parent.activate_node.call(this, obj, e); + } + }; + }; + + +/** + * ### Contextmenu plugin + * + * Shows a context menu when a node is right-clicked. + */ + + /** + * stores all defaults for the contextmenu plugin + * @name $.jstree.defaults.contextmenu + * @plugin contextmenu + */ + $.jstree.defaults.contextmenu = { + /** + * a boolean indicating if the node should be selected when the context menu is invoked on it. Defaults to `true`. + * @name $.jstree.defaults.contextmenu.select_node + * @plugin contextmenu + */ + select_node : true, + /** + * a boolean indicating if the menu should be shown aligned with the node. Defaults to `true`, otherwise the mouse coordinates are used. + * @name $.jstree.defaults.contextmenu.show_at_node + * @plugin contextmenu + */ + show_at_node : true, + /** + * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too). + * + * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required). Once a menu item is activated the `action` function will be invoked with an object containing the following keys: item - the contextmenu item definition as seen below, reference - the DOM node that was used (the tree node), element - the contextmenu DOM element, position - an object with x/y properties indicating the position of the menu. + * + * * `separator_before` - a boolean indicating if there should be a separator before this item + * * `separator_after` - a boolean indicating if there should be a separator after this item + * * `_disabled` - a boolean indicating if this action should be disabled + * * `label` - a string - the name of the action (could be a function returning a string) + * * `title` - a string - an optional tooltip for the item + * * `action` - a function to be executed if this item is chosen, the function will receive + * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2) + * * `shortcut_label` - shortcut label (like for example `F2` for rename) + * * `submenu` - an object with the same structure as $.jstree.defaults.contextmenu.items which can be used to create a submenu - each key will be rendered as a separate option in a submenu that will appear once the current item is hovered + * + * @name $.jstree.defaults.contextmenu.items + * @plugin contextmenu + */ + items : function (o, cb) { // Could be an object directly + return { + "create" : { + "separator_before" : false, + "separator_after" : true, + "_disabled" : false, //(this.check("create_node", data.reference, {}, "last")), + "label" : "Create", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.create_node(obj, {}, "last", function (new_node) { + setTimeout(function () { inst.edit(new_node); },0); + }); + } + }, + "rename" : { + "separator_before" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Rename", + /*! + "shortcut" : 113, + "shortcut_label" : 'F2', + "icon" : "glyphicon glyphicon-leaf", + */ + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.edit(obj); + } + }, + "remove" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Delete", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.delete_node(inst.get_selected()); + } + else { + inst.delete_node(obj); + } + } + }, + "ccp" : { + "separator_before" : true, + "icon" : false, + "separator_after" : false, + "label" : "Edit", + "action" : false, + "submenu" : { + "cut" : { + "separator_before" : false, + "separator_after" : false, + "label" : "Cut", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.cut(inst.get_top_selected()); + } + else { + inst.cut(obj); + } + } + }, + "copy" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Copy", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.copy(inst.get_top_selected()); + } + else { + inst.copy(obj); + } + } + }, + "paste" : { + "separator_before" : false, + "icon" : false, + "_disabled" : function (data) { + return !$.jstree.reference(data.reference).can_paste(); + }, + "separator_after" : false, + "label" : "Paste", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.paste(obj); + } + } + } + } + }; + } + }; + + $.jstree.plugins.contextmenu = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + var last_ts = 0, cto = null, ex, ey; + this.element + .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) { + if (e.target.tagName.toLowerCase() === 'input') { + return; + } + e.preventDefault(); + last_ts = e.ctrlKey ? +new Date() : 0; + if(data || cto) { + last_ts = (+new Date()) + 10000; + } + if(cto) { + clearTimeout(cto); + } + if(!this.is_loading(e.currentTarget)) { + this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e); + } + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts > 250)) { // work around safari & macOS ctrl+click + $.vakata.context.hide(); + } + last_ts = 0; + }, this)) + .on("touchstart.jstree", ".jstree-anchor", function (e) { + if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) { + return; + } + ex = e.originalEvent.changedTouches[0].clientX; + ey = e.originalEvent.changedTouches[0].clientY; + cto = setTimeout(function () { + $(e.currentTarget).trigger('contextmenu', true); + }, 750); + }) + .on('touchmove.vakata.jstree', function (e) { + if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.originalEvent.changedTouches[0].clientX) > 50 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 50)) { + clearTimeout(cto); + } + }) + .on('touchend.vakata.jstree', function (e) { + if(cto) { + clearTimeout(cto); + } + }); + + /*! + if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) { + var el = null, tm = null; + this.element + .on("touchstart", ".jstree-anchor", function (e) { + el = e.currentTarget; + tm = +new Date(); + $(document).one("touchend", function (e) { + e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset); + e.currentTarget = e.target; + tm = ((+(new Date())) - tm); + if(e.target === el && tm > 600 && tm < 1000) { + e.preventDefault(); + $(el).trigger('contextmenu', e); + } + el = null; + tm = null; + }); + }); + } + */ + $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) { + this._data.contextmenu.visible = false; + $(data.reference).removeClass('jstree-context'); + }, this)); + }; + this.teardown = function () { + if(this._data.contextmenu.visible) { + $.vakata.context.hide(); + } + parent.teardown.call(this); + }; + + /** + * prepare and show the context menu for a node + * @name show_contextmenu(obj [, x, y]) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Object} e the event if available that triggered the contextmenu + * @plugin contextmenu + * @trigger show_contextmenu.jstree + */ + this.show_contextmenu = function (obj, x, y, e) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var s = this.settings.contextmenu, + d = this.get_node(obj, true), + a = d.children(".jstree-anchor"), + o = false, + i = false; + if(s.show_at_node || x === undefined || y === undefined) { + o = a.offset(); + x = o.left; + y = o.top + this._data.core.li_height; + } + if(this.settings.contextmenu.select_node && !this.is_selected(obj)) { + this.activate_node(obj, e); + } + + i = s.items; + if($.isFunction(i)) { + i = i.call(this, obj, $.proxy(function (i) { + this._show_contextmenu(obj, x, y, i); + }, this)); + } + if($.isPlainObject(i)) { + this._show_contextmenu(obj, x, y, i); + } + }; + /** + * show the prepared context menu for a node + * @name _show_contextmenu(obj, x, y, i) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Number} i the object of items to show + * @plugin contextmenu + * @trigger show_contextmenu.jstree + * @private + */ + this._show_contextmenu = function (obj, x, y, i) { + var d = this.get_node(obj, true), + a = d.children(".jstree-anchor"); + $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) { + var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu'; + $(data.element).addClass(cls); + a.addClass('jstree-context'); + }, this)); + this._data.contextmenu.visible = true; + $.vakata.context.show(a, { 'x' : x, 'y' : y }, i); + /** + * triggered when the contextmenu is shown for a node + * @event + * @name show_contextmenu.jstree + * @param {Object} node the node + * @param {Number} x the x-coordinate of the menu relative to the document + * @param {Number} y the y-coordinate of the menu relative to the document + * @plugin contextmenu + */ + this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y }); + }; + }; + + // contextmenu helper + (function ($) { + var right_to_left = false, + vakata_context = { + element : false, + reference : false, + position_x : 0, + position_y : 0, + items : [], + html : "", + is_visible : false + }; + + $.vakata.context = { + settings : { + hide_onmouseleave : 0, + icons : true + }, + _trigger : function (event_name) { + $(document).triggerHandler("context_" + event_name + ".vakata", { + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }); + }, + _execute : function (i) { + i = vakata_context.items[i]; + return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, { + "item" : i, + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }) : false; + }, + _parse : function (o, is_callback) { + if(!o) { return false; } + if(!is_callback) { + vakata_context.html = ""; + vakata_context.items = []; + } + var str = "", + sep = false, + tmp; + + if(is_callback) { str += "<"+"ul>"; } + $.each(o, function (i, val) { + if(!val) { return true; } + vakata_context.items.push(val); + if(!sep && val.separator_before) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + } + sep = false; + str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">"; + str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">"; + if($.vakata.context.settings.icons) { + str += "<"+"i "; + if(val.icon) { + if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; } + else { str += " class='" + val.icon + "' "; } + } + str += "><"+"/i><"+"span class='vakata-contextmenu-sep'> <"+"/span>"; + } + str += ($.isFunction(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' <span class="vakata-contextmenu-shortcut vakata-contextmenu-shortcut-'+val.shortcut+'">'+ (val.shortcut_label || '') +'</span>':'') + "<"+"/a>"; + if(val.submenu) { + tmp = $.vakata.context._parse(val.submenu, true); + if(tmp) { str += tmp; } + } + str += "<"+"/li>"; + if(val.separator_after) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + sep = true; + } + }); + str = str.replace(/<li class\='vakata-context-separator'\><\/li\>$/,""); + if(is_callback) { str += "</ul>"; } + /** + * triggered on the document when the contextmenu is parsed (HTML is built) + * @event + * @plugin contextmenu + * @name context_parse.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); } + return str.length > 10 ? str : false; + }, + _show_submenu : function (o) { + o = $(o); + if(!o.length || !o.children("ul").length) { return; } + var e = o.children("ul"), + xl = o.offset().left, + x = xl + o.outerWidth(), + y = o.offset().top, + w = e.width(), + h = e.height(), + dw = $(window).width() + $(window).scrollLeft(), + dh = $(window).height() + $(window).scrollTop(); + // може да Ñе ÑпеÑти е една проверка - дали нÑма нÑкой от клаÑовете вече нагоре + if(right_to_left) { + o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left"); + } + else { + o[x + w > dw && xl > dw - x ? "addClass" : "removeClass"]("vakata-context-right"); + } + if(y + h + 10 > dh) { + e.css("bottom","-1px"); + } + + //if does not fit - stick it to the side + if (o.hasClass('vakata-context-right')) { + if (xl < w) { + e.css("margin-right", xl - w); + } + } else { + if (dw - x < w) { + e.css("margin-left", dw - x - w); + } + } + + e.show(); + }, + show : function (reference, position, data) { + var o, e, x, y, w, h, dw, dh, cond = true; + if(vakata_context.element && vakata_context.element.length) { + vakata_context.element.width(''); + } + switch(cond) { + case (!position && !reference): + return false; + case (!!position && !!reference): + vakata_context.reference = reference; + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + case (!position && !!reference): + vakata_context.reference = reference; + o = reference.offset(); + vakata_context.position_x = o.left + reference.outerHeight(); + vakata_context.position_y = o.top; + break; + case (!!position && !reference): + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + } + if(!!reference && !data && $(reference).data('vakata_contextmenu')) { + data = $(reference).data('vakata_contextmenu'); + } + if($.vakata.context._parse(data)) { + vakata_context.element.html(vakata_context.html); + } + if(vakata_context.items.length) { + vakata_context.element.appendTo("body"); + e = vakata_context.element; + x = vakata_context.position_x; + y = vakata_context.position_y; + w = e.width(); + h = e.height(); + dw = $(window).width() + $(window).scrollLeft(); + dh = $(window).height() + $(window).scrollTop(); + if(right_to_left) { + x -= (e.outerWidth() - $(reference).outerWidth()); + if(x < $(window).scrollLeft() + 20) { + x = $(window).scrollLeft() + 20; + } + } + if(x + w + 20 > dw) { + x = dw - (w + 20); + } + if(y + h + 20 > dh) { + y = dh - (h + 20); + } + + vakata_context.element + .css({ "left" : x, "top" : y }) + .show() + .find('a').first().focus().parent().addClass("vakata-context-hover"); + vakata_context.is_visible = true; + /** + * triggered on the document when the contextmenu is shown + * @event + * @plugin contextmenu + * @name context_show.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("show"); + } + }, + hide : function () { + if(vakata_context.is_visible) { + vakata_context.element.hide().find("ul").hide().end().find(':focus').blur().end().detach(); + vakata_context.is_visible = false; + /** + * triggered on the document when the contextmenu is hidden + * @event + * @plugin contextmenu + * @name context_hide.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("hide"); + } + } + }; + $(function () { + right_to_left = $("body").css("direction") === "rtl"; + var to = false; + + vakata_context.element = $("<ul class='vakata-context'></ul>"); + vakata_context.element + .on("mouseenter", "li", function (e) { + e.stopImmediatePropagation(); + + if($.contains(this, e.relatedTarget)) { + // премахнато заради delegate mouseleave по-долу + // $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + return; + } + + if(to) { clearTimeout(to); } + vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(); + + $(this) + .siblings().find("ul").hide().end().end() + .parentsUntil(".vakata-context", "li").addBack().addClass("vakata-context-hover"); + $.vakata.context._show_submenu(this); + }) + // теÑтово - дали не натоварва? + .on("mouseleave", "li", function (e) { + if($.contains(this, e.relatedTarget)) { return; } + $(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover"); + }) + .on("mouseleave", function (e) { + $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + if($.vakata.context.settings.hide_onmouseleave) { + to = setTimeout( + (function (t) { + return function () { $.vakata.context.hide(); }; + }(this)), $.vakata.context.settings.hide_onmouseleave); + } + }) + .on("click", "a", function (e) { + e.preventDefault(); + //}) + //.on("mouseup", "a", function (e) { + if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) { + $.vakata.context.hide(); + } + }) + .on('keydown', 'a', function (e) { + var o = null; + switch(e.which) { + case 13: + case 32: + e.type = "click"; + e.preventDefault(); + $(e.currentTarget).trigger(e); + break; + case 37: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 38: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 39: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 40: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 27: + $.vakata.context.hide(); + e.preventDefault(); + break; + default: + //console.log(e.which); + break; + } + }) + .on('keydown', function (e) { + e.preventDefault(); + var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent(); + if(a.parent().not('.vakata-context-disabled')) { + a.click(); + } + }); + + $(document) + .on("mousedown.vakata.jstree", function (e) { + if(vakata_context.is_visible && !$.contains(vakata_context.element[0], e.target)) { + $.vakata.context.hide(); + } + }) + .on("context_show.vakata.jstree", function (e, data) { + vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"); + if(right_to_left) { + vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl"); + } + // also apply a RTL class? + vakata_context.element.find("ul").hide().end(); + }); + }); + }($)); + // $.jstree.defaults.plugins.push("contextmenu"); + + +/** + * ### Drag'n'drop plugin + * + * Enables dragging and dropping of nodes in the tree, resulting in a move or copy operations. + */ + + /** + * stores all defaults for the drag'n'drop plugin + * @name $.jstree.defaults.dnd + * @plugin dnd + */ + $.jstree.defaults.dnd = { + /** + * a boolean indicating if a copy should be possible while dragging (by pressint the meta key or Ctrl). Defaults to `true`. + * @name $.jstree.defaults.dnd.copy + * @plugin dnd + */ + copy : true, + /** + * a number indicating how long a node should remain hovered while dragging to be opened. Defaults to `500`. + * @name $.jstree.defaults.dnd.open_timeout + * @plugin dnd + */ + open_timeout : 500, + /** + * a function invoked each time a node is about to be dragged, invoked in the tree's scope and receives the nodes about to be dragged as an argument (array) and the event that started the drag - return `false` to prevent dragging + * @name $.jstree.defaults.dnd.is_draggable + * @plugin dnd + */ + is_draggable : true, + /** + * a boolean indicating if checks should constantly be made while the user is dragging the node (as opposed to checking only on drop), default is `true` + * @name $.jstree.defaults.dnd.check_while_dragging + * @plugin dnd + */ + check_while_dragging : true, + /** + * a boolean indicating if nodes from this tree should only be copied with dnd (as opposed to moved), default is `false` + * @name $.jstree.defaults.dnd.always_copy + * @plugin dnd + */ + always_copy : false, + /** + * when dropping a node "inside", this setting indicates the position the node should go to - it can be an integer or a string: "first" (same as 0) or "last", default is `0` + * @name $.jstree.defaults.dnd.inside_pos + * @plugin dnd + */ + inside_pos : 0, + /** + * when starting the drag on a node that is selected this setting controls if all selected nodes are dragged or only the single node, default is `true`, which means all selected nodes are dragged when the drag is started on a selected node + * @name $.jstree.defaults.dnd.drag_selection + * @plugin dnd + */ + drag_selection : true, + /** + * controls whether dnd works on touch devices. If left as boolean true dnd will work the same as in desktop browsers, which in some cases may impair scrolling. If set to boolean false dnd will not work on touch devices. There is a special third option - string "selected" which means only selected nodes can be dragged on touch devices. + * @name $.jstree.defaults.dnd.touch + * @plugin dnd + */ + touch : true, + /** + * controls whether items can be dropped anywhere on the node, not just on the anchor, by default only the node anchor is a valid drop target. Works best with the wholerow plugin. If enabled on mobile depending on the interface it might be hard for the user to cancel the drop, since the whole tree container will be a valid drop target. + * @name $.jstree.defaults.dnd.large_drop_target + * @plugin dnd + */ + large_drop_target : false, + /** + * controls whether a drag can be initiated from any part of the node and not just the text/icon part, works best with the wholerow plugin. Keep in mind it can cause problems with tree scrolling on mobile depending on the interface - in that case set the touch option to "selected". + * @name $.jstree.defaults.dnd.large_drag_target + * @plugin dnd + */ + large_drag_target : false, + /** + * controls whether use HTML5 dnd api instead of classical. That will allow better integration of dnd events with other HTML5 controls. + * @reference http://caniuse.com/#feat=dragndrop + * @name $.jstree.defaults.dnd.use_html5 + * @plugin dnd + */ + use_html5: false + }; + var drg, elm; + // TODO: now check works by checking for each node individually, how about max_children, unique, etc? + $.jstree.plugins.dnd = function (options, parent) { + this.init = function (el, options) { + parent.init.call(this, el, options); + this.settings.dnd.use_html5 = this.settings.dnd.use_html5 && ('draggable' in document.createElement('span')); + }; + this.bind = function () { + parent.bind.call(this); + + this.element + .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) { + if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) { + return true; + } + if(e.type === "touchstart" && (!this.settings.dnd.touch || (this.settings.dnd.touch === 'selected' && !$(e.currentTarget).closest('.jstree-node').children('.jstree-anchor').hasClass('jstree-clicked')))) { + return true; + } + var obj = this.get_node(e.target), + mlt = this.is_selected(obj) && this.settings.dnd.drag_selection ? this.get_top_selected().length : 1, + txt = (mlt > 1 ? mlt + ' ' + this.get_string('nodes') : this.get_text(e.currentTarget)); + if(this.settings.core.force_text) { + txt = $.vakata.html.escape(txt); + } + if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") && + (this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e))) + ) { + drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] }; + elm = e.currentTarget; + if (this.settings.dnd.use_html5) { + $.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg }); + } else { + this.element.trigger('mousedown.jstree'); + return $.vakata.dnd.start(e, drg, '<div id="jstree-dnd" class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' + this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' + txt + '<ins class="jstree-copy" style="display:none;">+</ins></div>'); + } + } + }, this)); + if (this.settings.dnd.use_html5) { + this.element + .on('dragover.jstree', function (e) { + e.preventDefault(); + $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg }); + return false; + }) + //.on('dragenter.jstree', this.settings.dnd.large_drop_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) { + // e.preventDefault(); + // $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg }); + // return false; + // }, this)) + .on('drop.jstree', $.proxy(function (e) { + e.preventDefault(); + $.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg }); + return false; + }, this)); + } + }; + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if (obj && this.settings.dnd.use_html5) { + if (this.settings.dnd.large_drag_target) { + obj.setAttribute('draggable', true); + } else { + var i, j, tmp = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + tmp.setAttribute('draggable', true); + } + } + } + return obj; + }; + }; + + $(function() { + // bind only once for all instances + var lastmv = false, + laster = false, + lastev = false, + opento = false, + marker = $('<div id="jstree-marker"> </div>').hide(); //.appendTo('body'); + + $(document) + .on('dnd_start.vakata.jstree', function (e, data) { + lastmv = false; + lastev = false; + if(!data || !data.data || !data.data.jstree) { return; } + marker.appendTo('body'); //.show(); + }) + .on('dnd_move.vakata.jstree', function (e, data) { + if(opento) { + if (!data.event || data.event.type !== 'dragover' || data.event.target !== lastev.target) { + clearTimeout(opento); + } + } + if(!data || !data.data || !data.data.jstree) { return; } + + // if we are hovering the marker image do nothing (can happen on "inside" drags) + if(data.event.target.id && data.event.target.id === 'jstree-marker') { + return; + } + lastev = data.event; + + var ins = $.jstree.reference(data.event.target), + ref = false, + off = false, + rel = false, + tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm, is_copy, pn; + // if we are over an instance + if(ins && ins._data && ins._data.dnd) { + marker.attr('class', 'jstree-' + ins.get_theme() + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' )); + is_copy = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))); + data.helper + .children().attr('class', 'jstree-' + ins.get_theme() + ' jstree-' + ins.get_theme() + '-' + ins.get_theme_variant() + ' ' + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' )) + .find('.jstree-copy').first()[ is_copy ? 'show' : 'hide' ](); + + // if are hovering the container itself add a new root node + //console.log(data.event); + if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) { + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + ok = ok && ins.check( (data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' : ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }); + if(!ok) { break; } + } + if(ok) { + lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' }; + marker.hide(); + data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move'; + } + return; + } + } + else { + // if we are hovering a tree node + ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor'); + if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) { + off = ref.offset(); + rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top; + h = ref.outerHeight(); + if(rel < h / 3) { + o = ['b', 'i', 'a']; + } + else if(rel > h - h / 3) { + o = ['a', 'i', 'b']; + } + else { + o = rel > h / 2 ? ['i', 'a', 'b'] : ['i', 'b', 'a']; + } + $.each(o, function (j, v) { + switch(v) { + case 'b': + l = off.left - 6; + t = off.top; + p = ins.get_parent(ref); + i = ref.parent().index(); + break; + case 'i': + ip = ins.settings.dnd.inside_pos; + tm = ins.get_node(ref.parent()); + l = off.left - 2; + t = off.top + h / 2 + 1; + p = tm.id; + i = ip === 'first' ? 0 : (ip === 'last' ? tm.children.length : Math.min(ip, tm.children.length)); + break; + case 'a': + l = off.left - 6; + t = off.top + h; + p = ins.get_parent(ref); + i = ref.parent().index() + 1; + break; + } + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + op = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? "copy_node" : "move_node"; + ps = i; + if(op === "move_node" && v === 'a' && (data.data.origin && data.data.origin === ins) && p === ins.get_parent(data.data.nodes[t1])) { + pr = ins.get_node(p); + if(ps > $.inArray(data.data.nodes[t1], pr.children)) { + ps -= 1; + } + } + ok = ok && ( (ins && ins.settings && ins.settings.dnd && ins.settings.dnd.check_while_dragging === false) || ins.check(op, (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, { 'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }) ); + if(!ok) { + if(ins && ins.last_error) { laster = ins.last_error(); } + break; + } + } + if(v === 'i' && ref.parent().is('.jstree-closed') && ins.settings.dnd.open_timeout) { + opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout); + } + if(ok) { + pn = ins.get_node(p, true); + if (!pn.hasClass('.jstree-dnd-parent')) { + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + pn.addClass('jstree-dnd-parent'); + } + lastmv = { 'ins' : ins, 'par' : p, 'pos' : v === 'i' && ip === 'last' && i === 0 && !ins.is_loaded(tm) ? 'last' : i }; + marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show(); + data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move'; + } + laster = {}; + o = true; + return false; + } + }); + if(o === true) { return; } + } + } + } + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + lastmv = false; + data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = 'none'; + } + marker.hide(); + }) + .on('dnd_scroll.vakata.jstree', function (e, data) { + if(!data || !data.data || !data.data.jstree) { return; } + marker.hide(); + lastmv = false; + lastev = false; + data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er'); + }) + .on('dnd_stop.vakata.jstree', function (e, data) { + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + if(opento) { clearTimeout(opento); } + if(!data || !data.data || !data.data.jstree) { return; } + marker.hide().detach(); + var i, j, nodes = []; + if(lastmv) { + for(i = 0, j = data.data.nodes.length; i < j; i++) { + nodes[i] = data.data.origin ? data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i]; + } + lastmv.ins[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par, lastmv.pos, false, false, false, data.data.origin); + } + else { + i = $(data.event.target).closest('.jstree'); + if(i.length && laster && laster.error && laster.error === 'check') { + i = i.jstree(true); + if(i) { + i.settings.core.error.call(this, laster); + } + } + } + lastev = false; + lastmv = false; + }) + .on('keyup.jstree keydown.jstree', function (e, data) { + data = $.vakata.dnd._get(); + if(data && data.data && data.data.jstree) { + if (e.type === "keyup" && e.which === 27) { + if (opento) { clearTimeout(opento); } + lastmv = false; + laster = false; + lastev = false; + opento = false; + marker.hide().detach(); + $.vakata.dnd._clean(); + } else { + data.helper.find('.jstree-copy').first()[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey))) ? 'show' : 'hide' ](); + if(lastev) { + lastev.metaKey = e.metaKey; + lastev.ctrlKey = e.ctrlKey; + $.vakata.dnd._trigger('move', lastev); + } + } + } + }); + }); + + // helpers + (function ($) { + $.vakata.html = { + div : $('<div />'), + escape : function (str) { + return $.vakata.html.div.text(str).html(); + }, + strip : function (str) { + return $.vakata.html.div.empty().append($.parseHTML(str)).text(); + } + }; + // private variable + var vakata_dnd = { + element : false, + target : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false, + is_touch: false + }; + $.vakata.dnd = { + settings : { + scroll_speed : 10, + scroll_proximity : 20, + helper_left : 5, + helper_top : 10, + threshold : 5, + threshold_touch : 50 + }, + _trigger : function (event_name, e, data) { + if (data === undefined) { + data = $.vakata.dnd._get(); + } + data.event = e; + $(document).triggerHandler("dnd_" + event_name + ".vakata", data); + }, + _get : function () { + return { + "data" : vakata_dnd.data, + "element" : vakata_dnd.element, + "helper" : vakata_dnd.helper + }; + }, + _clean : function () { + if(vakata_dnd.helper) { vakata_dnd.helper.remove(); } + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + vakata_dnd = { + element : false, + target : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false, + is_touch: false + }; + $(document).off("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag); + $(document).off("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop); + }, + _scroll : function (init_only) { + if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) { + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + return false; + } + if(!vakata_dnd.scroll_i) { + vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100); + return false; + } + if(init_only === true) { return false; } + + var i = vakata_dnd.scroll_e.scrollTop(), + j = vakata_dnd.scroll_e.scrollLeft(); + vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed); + vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed); + if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) { + /** + * triggered on the document when a drag causes an element to scroll + * @event + * @plugin dnd + * @name dnd_scroll.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {jQuery} event the element that is scrolling + */ + $.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e); + } + }, + start : function (e, data, html) { + if(e.type === "touchstart" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); } + try { + e.currentTarget.unselectable = "on"; + e.currentTarget.onselectstart = function() { return false; }; + if(e.currentTarget.style) { + e.currentTarget.style.touchAction = "none"; + e.currentTarget.style.msTouchAction = "none"; + e.currentTarget.style.MozUserSelect = "none"; + } + } catch(ignore) { } + vakata_dnd.init_x = e.pageX; + vakata_dnd.init_y = e.pageY; + vakata_dnd.data = data; + vakata_dnd.is_down = true; + vakata_dnd.element = e.currentTarget; + vakata_dnd.target = e.target; + vakata_dnd.is_touch = e.type === "touchstart"; + if(html !== false) { + vakata_dnd.helper = $("<div id='vakata-dnd'></div>").html(html).css({ + "display" : "block", + "margin" : "0", + "padding" : "0", + "position" : "absolute", + "top" : "-2000px", + "lineHeight" : "16px", + "zIndex" : "10000" + }); + } + $(document).on("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag); + $(document).on("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop); + return false; + }, + drag : function (e) { + if(e.type === "touchmove" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(!vakata_dnd.is_down) { return; } + if(!vakata_dnd.is_drag) { + if( + Math.abs(e.pageX - vakata_dnd.init_x) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) || + Math.abs(e.pageY - vakata_dnd.init_y) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) + ) { + if(vakata_dnd.helper) { + vakata_dnd.helper.appendTo("body"); + vakata_dnd.helper_w = vakata_dnd.helper.outerWidth(); + } + vakata_dnd.is_drag = true; + $(vakata_dnd.target).one('click.vakata', false); + /** + * triggered on the document when a drag starts + * @event + * @plugin dnd + * @name dnd_start.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the start (probably mousemove) + */ + $.vakata.dnd._trigger("start", e); + } + else { return; } + } + + var d = false, w = false, + dh = false, wh = false, + dw = false, ww = false, + dt = false, dl = false, + ht = false, hl = false; + + vakata_dnd.scroll_t = 0; + vakata_dnd.scroll_l = 0; + vakata_dnd.scroll_e = false; + $($(e.target).parentsUntil("body").addBack().get().reverse()) + .filter(function () { + return (/^auto|scroll$/).test($(this).css("overflow")) && + (this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth); + }) + .each(function () { + var t = $(this), o = t.offset(); + if(this.scrollHeight > this.offsetHeight) { + if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + } + if(this.scrollWidth > this.offsetWidth) { + if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = $(this); + return false; + } + }); + + if(!vakata_dnd.scroll_e) { + d = $(document); w = $(window); + dh = d.height(); wh = w.height(); + dw = d.width(); ww = w.width(); + dt = d.scrollTop(); dl = d.scrollLeft(); + if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = d; + } + } + if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); } + + if(vakata_dnd.helper) { + ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10); + hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10); + if(dh && ht + 25 > dh) { ht = dh - 50; } + if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); } + vakata_dnd.helper.css({ + left : hl + "px", + top : ht + "px" + }); + } + /** + * triggered on the document when a drag is in progress + * @event + * @plugin dnd + * @name dnd_move.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused this to trigger (most likely mousemove) + */ + $.vakata.dnd._trigger("move", e); + return false; + }, + stop : function (e) { + if(e.type === "touchend" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { + /** + * triggered on the document when a drag stops (the dragged element is dropped) + * @event + * @plugin dnd + * @name dnd_stop.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the stop + */ + if (e.target !== vakata_dnd.target) { + $(vakata_dnd.target).off('click.vakata'); + } + $.vakata.dnd._trigger("stop", e); + } + else { + if(e.type === "touchend" && e.target === vakata_dnd.target) { + var to = setTimeout(function () { $(e.target).click(); }, 100); + $(e.target).one('click', function() { if(to) { clearTimeout(to); } }); + } + } + $.vakata.dnd._clean(); + return false; + } + }; + }($)); + + // include the dnd plugin by default + // $.jstree.defaults.plugins.push("dnd"); + + +/** + * ### Massload plugin + * + * Adds massload functionality to jsTree, so that multiple nodes can be loaded in a single request (only useful with lazy loading). + */ + + /** + * massload configuration + * + * It is possible to set this to a standard jQuery-like AJAX config. + * In addition to the standard jQuery ajax options here you can supply functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node IDs need to be loaded, the return value of those functions will be used. + * + * You can also set this to a function, that function will receive the node IDs being loaded as argument and a second param which is a function (callback) which should be called with the result. + * + * Both the AJAX and the function approach rely on the same return value - an object where the keys are the node IDs, and the value is the children of that node as an array. + * + * { + * "id1" : [{ "text" : "Child of ID1", "id" : "c1" }, { "text" : "Another child of ID1", "id" : "c2" }], + * "id2" : [{ "text" : "Child of ID2", "id" : "c3" }] + * } + * + * @name $.jstree.defaults.massload + * @plugin massload + */ + $.jstree.defaults.massload = null; + $.jstree.plugins.massload = function (options, parent) { + this.init = function (el, options) { + this._data.massload = {}; + parent.init.call(this, el, options); + }; + this._load_nodes = function (nodes, callback, is_callback, force_reload) { + var s = this.settings.massload, + nodesString = JSON.stringify(nodes), + toLoad = [], + m = this._model.data, + i, j, dom; + if (!is_callback) { + for(i = 0, j = nodes.length; i < j; i++) { + if(!m[nodes[i]] || ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || force_reload) ) { + toLoad.push(nodes[i]); + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.addClass("jstree-loading").attr('aria-busy',true); + } + } + } + this._data.massload = {}; + if (toLoad.length) { + if($.isFunction(s)) { + return s.call(this, toLoad, $.proxy(function (data) { + var i, j; + if(data) { + for(i in data) { + if(data.hasOwnProperty(i)) { + this._data.massload[i] = data[i]; + } + } + } + for(i = 0, j = nodes.length; i < j; i++) { + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + } + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)); + } + if(typeof s === 'object' && s && s.url) { + s = $.extend(true, {}, s); + if($.isFunction(s.url)) { + s.url = s.url.call(this, toLoad); + } + if($.isFunction(s.data)) { + s.data = s.data.call(this, toLoad); + } + return $.ajax(s) + .done($.proxy(function (data,t,x) { + var i, j; + if(data) { + for(i in data) { + if(data.hasOwnProperty(i)) { + this._data.massload[i] = data[i]; + } + } + } + for(i = 0, j = nodes.length; i < j; i++) { + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + } + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)) + .fail($.proxy(function (f) { + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)); + } + } + } + return parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }; + this._load_node = function (obj, callback) { + var data = this._data.massload[obj.id], + rslt = null, dom; + if(data) { + rslt = this[typeof data === 'string' ? '_append_html_data' : '_append_json_data']( + obj, + typeof data === 'string' ? $($.parseHTML(data)).filter(function () { return this.nodeType !== 3; }) : data, + function (status) { callback.call(this, status); } + ); + dom = this.get_node(obj.id, true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + delete this._data.massload[obj.id]; + return rslt; + } + return parent._load_node.call(this, obj, callback); + }; + }; + +/** + * ### Search plugin + * + * Adds search functionality to jsTree. + */ + + /** + * stores all defaults for the search plugin + * @name $.jstree.defaults.search + * @plugin search + */ + $.jstree.defaults.search = { + /** + * a jQuery-like AJAX config, which jstree uses if a server should be queried for results. + * + * A `str` (which is the search string) parameter will be added with the request, an optional `inside` parameter will be added if the search is limited to a node id. The expected result is a JSON array with nodes that need to be opened so that matching nodes will be revealed. + * Leave this setting as `false` to not query the server. You can also set this to a function, which will be invoked in the instance's scope and receive 3 parameters - the search string, the callback to call with the array of nodes to load, and the optional node ID to limit the search to + * @name $.jstree.defaults.search.ajax + * @plugin search + */ + ajax : false, + /** + * Indicates if the search should be fuzzy or not (should `chnd3` match `child node 3`). Default is `false`. + * @name $.jstree.defaults.search.fuzzy + * @plugin search + */ + fuzzy : false, + /** + * Indicates if the search should be case sensitive. Default is `false`. + * @name $.jstree.defaults.search.case_sensitive + * @plugin search + */ + case_sensitive : false, + /** + * Indicates if the tree should be filtered (by default) to show only matching nodes (keep in mind this can be a heavy on large trees in old browsers). + * This setting can be changed at runtime when calling the search method. Default is `false`. + * @name $.jstree.defaults.search.show_only_matches + * @plugin search + */ + show_only_matches : false, + /** + * Indicates if the children of matched element are shown (when show_only_matches is true) + * This setting can be changed at runtime when calling the search method. Default is `false`. + * @name $.jstree.defaults.search.show_only_matches_children + * @plugin search + */ + show_only_matches_children : false, + /** + * Indicates if all nodes opened to reveal the search result, should be closed when the search is cleared or a new search is performed. Default is `true`. + * @name $.jstree.defaults.search.close_opened_onclear + * @plugin search + */ + close_opened_onclear : true, + /** + * Indicates if only leaf nodes should be included in search results. Default is `false`. + * @name $.jstree.defaults.search.search_leaves_only + * @plugin search + */ + search_leaves_only : false, + /** + * If set to a function it wil be called in the instance's scope with two arguments - search string and node (where node will be every node in the structure, so use with caution). + * If the function returns a truthy value the node will be considered a match (it might not be displayed if search_only_leaves is set to true and the node is not a leaf). Default is `false`. + * @name $.jstree.defaults.search.search_callback + * @plugin search + */ + search_callback : false + }; + + $.jstree.plugins.search = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this._data.search.str = ""; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.som = false; + this._data.search.smc = false; + this._data.search.hdn = []; + + this.element + .on("search.jstree", $.proxy(function (e, data) { + if(this._data.search.som && data.res.length) { + var m = this._model.data, i, j, p = [], k, l; + for(i = 0, j = data.res.length; i < j; i++) { + if(m[data.res[i]] && !m[data.res[i]].state.hidden) { + p.push(data.res[i]); + p = p.concat(m[data.res[i]].parents); + if(this._data.search.smc) { + for (k = 0, l = m[data.res[i]].children_d.length; k < l; k++) { + if (m[m[data.res[i]].children_d[k]] && !m[m[data.res[i]].children_d[k]].state.hidden) { + p.push(m[data.res[i]].children_d[k]); + } + } + } + } + } + p = $.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root); + this._data.search.hdn = this.hide_all(true); + this.show_node(p, true); + this.redraw(true); + } + }, this)) + .on("clear_search.jstree", $.proxy(function (e, data) { + if(this._data.search.som && data.res.length) { + this.show_node(this._data.search.hdn, true); + this.redraw(true); + } + }, this)); + }; + /** + * used to search the tree nodes for a given string + * @name search(str [, skip_async]) + * @param {String} str the search string + * @param {Boolean} skip_async if set to true server will not be queried even if configured + * @param {Boolean} show_only_matches if set to true only matching nodes will be shown (keep in mind this can be very slow on large trees or old browsers) + * @param {mixed} inside an optional node to whose children to limit the search + * @param {Boolean} append if set to true the results of this search are appended to the previous search + * @plugin search + * @trigger search.jstree + */ + this.search = function (str, skip_async, show_only_matches, inside, append, show_only_matches_children) { + if(str === false || $.trim(str.toString()) === "") { + return this.clear_search(); + } + inside = this.get_node(inside); + inside = inside && inside.id ? inside.id : null; + str = str.toString(); + var s = this.settings.search, + a = s.ajax ? s.ajax : false, + m = this._model.data, + f = null, + r = [], + p = [], i, j; + if(this._data.search.res.length && !append) { + this.clear_search(); + } + if(show_only_matches === undefined) { + show_only_matches = s.show_only_matches; + } + if(show_only_matches_children === undefined) { + show_only_matches_children = s.show_only_matches_children; + } + if(!skip_async && a !== false) { + if($.isFunction(a)) { + return a.call(this, str, $.proxy(function (d) { + if(d && d.d) { d = d.d; } + this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () { + this.search(str, true, show_only_matches, inside, append, show_only_matches_children); + }); + }, this), inside); + } + else { + a = $.extend({}, a); + if(!a.data) { a.data = {}; } + a.data.str = str; + if(inside) { + a.data.inside = inside; + } + if (this._data.search.lastRequest) { + this._data.search.lastRequest.abort(); + } + this._data.search.lastRequest = $.ajax(a) + .fail($.proxy(function () { + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)) + .done($.proxy(function (d) { + if(d && d.d) { d = d.d; } + this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () { + this.search(str, true, show_only_matches, inside, append, show_only_matches_children); + }); + }, this)); + return this._data.search.lastRequest; + } + } + if(!append) { + this._data.search.str = str; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.som = show_only_matches; + this._data.search.smc = show_only_matches_children; + } + + f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy }); + $.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) { + var v = m[i]; + if(v.text && !v.state.hidden && (!s.search_leaves_only || (v.state.loaded && v.children.length === 0)) && ( (s.search_callback && s.search_callback.call(this, str, v)) || (!s.search_callback && f.search(v.text).isMatch) ) ) { + r.push(i); + p = p.concat(v.parents); + } + }); + if(r.length) { + p = $.vakata.array_unique(p); + for(i = 0, j = p.length; i < j; i++) { + if(p[i] !== $.jstree.root && m[p[i]] && this.open_node(p[i], null, 0) === true) { + this._data.search.opn.push(p[i]); + } + } + if(!append) { + this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #'))); + this._data.search.res = r; + } + else { + this._data.search.dom = this._data.search.dom.add($(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #')))); + this._data.search.res = $.vakata.array_unique(this._data.search.res.concat(r)); + } + this._data.search.dom.children(".jstree-anchor").addClass('jstree-search'); + } + /** + * triggered after search is complete + * @event + * @name search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes + * @param {String} str the search string + * @param {Array} res a collection of objects represeing the matching nodes + * @plugin search + */ + this.trigger('search', { nodes : this._data.search.dom, str : str, res : this._data.search.res, show_only_matches : show_only_matches }); + }; + /** + * used to clear the last search (removes classes and shows all nodes if filtering is on) + * @name clear_search() + * @plugin search + * @trigger clear_search.jstree + */ + this.clear_search = function () { + if(this.settings.search.close_opened_onclear) { + this.close_node(this._data.search.opn, 0); + } + /** + * triggered after search is complete + * @event + * @name clear_search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes (the result from the last search) + * @param {String} str the search string (the last search string) + * @param {Array} res a collection of objects represeing the matching nodes (the result from the last search) + * @plugin search + */ + this.trigger('clear_search', { 'nodes' : this._data.search.dom, str : this._data.search.str, res : this._data.search.res }); + if(this._data.search.res.length) { + this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(this._data.search.res, function (v) { + return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); + }).join(', #'))); + this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search"); + } + this._data.search.str = ""; + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.dom = $(); + }; + + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + if($.inArray(obj.id, this._data.search.res) !== -1) { + var i, j, tmp = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + tmp.className += ' jstree-search'; + } + } + } + return obj; + }; + }; + + // helpers + (function ($) { + // from http://kiro.me/projects/fuse.html + $.vakata.search = function(pattern, txt, options) { + options = options || {}; + options = $.extend({}, $.vakata.search.defaults, options); + if(options.fuzzy !== false) { + options.fuzzy = true; + } + pattern = options.caseSensitive ? pattern : pattern.toLowerCase(); + var MATCH_LOCATION = options.location, + MATCH_DISTANCE = options.distance, + MATCH_THRESHOLD = options.threshold, + patternLen = pattern.length, + matchmask, pattern_alphabet, match_bitapScore, search; + if(patternLen > 32) { + options.fuzzy = false; + } + if(options.fuzzy) { + matchmask = 1 << (patternLen - 1); + pattern_alphabet = (function () { + var mask = {}, + i = 0; + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] = 0; + } + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] |= 1 << (patternLen - i - 1); + } + return mask; + }()); + match_bitapScore = function (e, x) { + var accuracy = e / patternLen, + proximity = Math.abs(MATCH_LOCATION - x); + if(!MATCH_DISTANCE) { + return proximity ? 1.0 : accuracy; + } + return accuracy + (proximity / MATCH_DISTANCE); + }; + } + search = function (text) { + text = options.caseSensitive ? text : text.toLowerCase(); + if(pattern === text || text.indexOf(pattern) !== -1) { + return { + isMatch: true, + score: 0 + }; + } + if(!options.fuzzy) { + return { + isMatch: false, + score: 1 + }; + } + var i, j, + textLen = text.length, + scoreThreshold = MATCH_THRESHOLD, + bestLoc = text.indexOf(pattern, MATCH_LOCATION), + binMin, binMid, + binMax = patternLen + textLen, + lastRd, start, finish, rd, charMatch, + score = 1, + locations = []; + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + bestLoc = text.lastIndexOf(pattern, MATCH_LOCATION + patternLen); + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + } + } + bestLoc = -1; + for (i = 0; i < patternLen; i++) { + binMin = 0; + binMid = binMax; + while (binMin < binMid) { + if (match_bitapScore(i, MATCH_LOCATION + binMid) <= scoreThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } + binMax = binMid; + start = Math.max(1, MATCH_LOCATION - binMid + 1); + finish = Math.min(MATCH_LOCATION + binMid, textLen) + patternLen; + rd = new Array(finish + 2); + rd[finish + 1] = (1 << i) - 1; + for (j = finish; j >= start; j--) { + charMatch = pattern_alphabet[text.charAt(j - 1)]; + if (i === 0) { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; + } else { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | (((lastRd[j + 1] | lastRd[j]) << 1) | 1) | lastRd[j + 1]; + } + if (rd[j] & matchmask) { + score = match_bitapScore(i, j - 1); + if (score <= scoreThreshold) { + scoreThreshold = score; + bestLoc = j - 1; + locations.push(bestLoc); + if (bestLoc > MATCH_LOCATION) { + start = Math.max(1, 2 * MATCH_LOCATION - bestLoc); + } else { + break; + } + } + } + } + if (match_bitapScore(i + 1, MATCH_LOCATION) > scoreThreshold) { + break; + } + lastRd = rd; + } + return { + isMatch: bestLoc >= 0, + score: score + }; + }; + return txt === true ? { 'search' : search } : search(txt); + }; + $.vakata.search.defaults = { + location : 0, + distance : 100, + threshold : 0.6, + fuzzy : false, + caseSensitive : false + }; + }($)); + + // include the search plugin by default + // $.jstree.defaults.plugins.push("search"); + + +/** + * ### Sort plugin + * + * Automatically sorts all siblings in the tree according to a sorting function. + */ + + /** + * the settings function used to sort the nodes. + * It is executed in the tree's context, accepts two nodes as arguments and should return `1` or `-1`. + * @name $.jstree.defaults.sort + * @plugin sort + */ + $.jstree.defaults.sort = function (a, b) { + //return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : this.get_type(a) >= this.get_type(b); + return this.get_text(a) > this.get_text(b) ? 1 : -1; + }; + $.jstree.plugins.sort = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this.element + .on("model.jstree", $.proxy(function (e, data) { + this.sort(data.parent, true); + }, this)) + .on("rename_node.jstree create_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent || data.node.parent, false); + this.redraw_node(data.parent || data.node.parent, true); + }, this)) + .on("move_node.jstree copy_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent, false); + this.redraw_node(data.parent, true); + }, this)); + }; + /** + * used to sort a node's children + * @private + * @name sort(obj [, deep]) + * @param {mixed} obj the node + * @param {Boolean} deep if set to `true` nodes are sorted recursively. + * @plugin sort + * @trigger search.jstree + */ + this.sort = function (obj, deep) { + var i, j; + obj = this.get_node(obj); + if(obj && obj.children && obj.children.length) { + obj.children.sort($.proxy(this.settings.sort, this)); + if(deep) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + this.sort(obj.children_d[i], false); + } + } + } + }; + }; + + // include the sort plugin by default + // $.jstree.defaults.plugins.push("sort"); + +/** + * ### State plugin + * + * Saves the state of the tree (selected nodes, opened nodes) on the user's computer using available options (localStorage, cookies, etc) + */ + + var to = false; + /** + * stores all defaults for the state plugin + * @name $.jstree.defaults.state + * @plugin state + */ + $.jstree.defaults.state = { + /** + * A string for the key to use when saving the current tree (change if using multiple trees in your project). Defaults to `jstree`. + * @name $.jstree.defaults.state.key + * @plugin state + */ + key : 'jstree', + /** + * A space separated list of events that trigger a state save. Defaults to `changed.jstree open_node.jstree close_node.jstree`. + * @name $.jstree.defaults.state.events + * @plugin state + */ + events : 'changed.jstree open_node.jstree close_node.jstree check_node.jstree uncheck_node.jstree', + /** + * Time in milliseconds after which the state will expire. Defaults to 'false' meaning - no expire. + * @name $.jstree.defaults.state.ttl + * @plugin state + */ + ttl : false, + /** + * A function that will be executed prior to restoring state with one argument - the state object. Can be used to clear unwanted parts of the state. + * @name $.jstree.defaults.state.filter + * @plugin state + */ + filter : false + }; + $.jstree.plugins.state = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + var bind = $.proxy(function () { + this.element.on(this.settings.state.events, $.proxy(function () { + if(to) { clearTimeout(to); } + to = setTimeout($.proxy(function () { this.save_state(); }, this), 100); + }, this)); + /** + * triggered when the state plugin is finished restoring the state (and immediately after ready if there is no state to restore). + * @event + * @name state_ready.jstree + * @plugin state + */ + this.trigger('state_ready'); + }, this); + this.element + .on("ready.jstree", $.proxy(function (e, data) { + this.element.one("restore_state.jstree", bind); + if(!this.restore_state()) { bind(); } + }, this)); + }; + /** + * save the state + * @name save_state() + * @plugin state + */ + this.save_state = function () { + var st = { 'state' : this.get_state(), 'ttl' : this.settings.state.ttl, 'sec' : +(new Date()) }; + $.vakata.storage.set(this.settings.state.key, JSON.stringify(st)); + }; + /** + * restore the state from the user's computer + * @name restore_state() + * @plugin state + */ + this.restore_state = function () { + var k = $.vakata.storage.get(this.settings.state.key); + if(!!k) { try { k = JSON.parse(k); } catch(ex) { return false; } } + if(!!k && k.ttl && k.sec && +(new Date()) - k.sec > k.ttl) { return false; } + if(!!k && k.state) { k = k.state; } + if(!!k && $.isFunction(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); } + if(!!k) { + this.element.one("set_state.jstree", function (e, data) { data.instance.trigger('restore_state', { 'state' : $.extend(true, {}, k) }); }); + this.set_state(k); + return true; + } + return false; + }; + /** + * clear the state on the user's computer + * @name clear_state() + * @plugin state + */ + this.clear_state = function () { + return $.vakata.storage.del(this.settings.state.key); + }; + }; + + (function ($, undefined) { + $.vakata.storage = { + // simply specifying the functions in FF throws an error + set : function (key, val) { return window.localStorage.setItem(key, val); }, + get : function (key) { return window.localStorage.getItem(key); }, + del : function (key) { return window.localStorage.removeItem(key); } + }; + }($)); + + // include the state plugin by default + // $.jstree.defaults.plugins.push("state"); + +/** + * ### Types plugin + * + * Makes it possible to add predefined types for groups of nodes, which make it possible to easily control nesting rules and icon for each group. + */ + + /** + * An object storing all types as key value pairs, where the key is the type name and the value is an object that could contain following keys (all optional). + * + * * `max_children` the maximum number of immediate children this node type can have. Do not specify or set to `-1` for unlimited. + * * `max_depth` the maximum number of nesting this node type can have. A value of `1` would mean that the node can have children, but no grandchildren. Do not specify or set to `-1` for unlimited. + * * `valid_children` an array of node type strings, that nodes of this type can have as children. Do not specify or set to `-1` for no limits. + * * `icon` a string - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class. Omit to use the default icon from your theme. + * * `li_attr` an object of values which will be used to add HTML attributes on the resulting LI DOM node (merged with the node's own data) + * * `a_attr` an object of values which will be used to add HTML attributes on the resulting A DOM node (merged with the node's own data) + * + * There are two predefined types: + * + * * `#` represents the root of the tree, for example `max_children` would control the maximum number of root nodes. + * * `default` represents the default node - any settings here will be applied to all nodes that do not have a type specified. + * + * @name $.jstree.defaults.types + * @plugin types + */ + $.jstree.defaults.types = { + 'default' : {} + }; + $.jstree.defaults.types[$.jstree.root] = {}; + + $.jstree.plugins.types = function (options, parent) { + this.init = function (el, options) { + var i, j; + if(options && options.types && options.types['default']) { + for(i in options.types) { + if(i !== "default" && i !== $.jstree.root && options.types.hasOwnProperty(i)) { + for(j in options.types['default']) { + if(options.types['default'].hasOwnProperty(j) && options.types[i][j] === undefined) { + options.types[i][j] = options.types['default'][j]; + } + } + } + } + } + parent.init.call(this, el, options); + this._model.data[$.jstree.root].type = $.jstree.root; + }; + this.refresh = function (skip_loading, forget_state) { + parent.refresh.call(this, skip_loading, forget_state); + this._model.data[$.jstree.root].type = $.jstree.root; + }; + this.bind = function () { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + dpc = data.nodes, + t = this.settings.types, + i, j, c = 'default', k; + for(i = 0, j = dpc.length; i < j; i++) { + c = 'default'; + if(m[dpc[i]].original && m[dpc[i]].original.type && t[m[dpc[i]].original.type]) { + c = m[dpc[i]].original.type; + } + if(m[dpc[i]].data && m[dpc[i]].data.jstree && m[dpc[i]].data.jstree.type && t[m[dpc[i]].data.jstree.type]) { + c = m[dpc[i]].data.jstree.type; + } + m[dpc[i]].type = c; + if(m[dpc[i]].icon === true && t[c].icon !== undefined) { + m[dpc[i]].icon = t[c].icon; + } + if(t[c].li_attr !== undefined && typeof t[c].li_attr === 'object') { + for (k in t[c].li_attr) { + if (t[c].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[dpc[i]].li_attr[k] === undefined) { + m[dpc[i]].li_attr[k] = t[c].li_attr[k]; + } + else if (k === 'class') { + m[dpc[i]].li_attr['class'] = t[c].li_attr['class'] + ' ' + m[dpc[i]].li_attr['class']; + } + } + } + } + if(t[c].a_attr !== undefined && typeof t[c].a_attr === 'object') { + for (k in t[c].a_attr) { + if (t[c].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[dpc[i]].a_attr[k] === undefined) { + m[dpc[i]].a_attr[k] = t[c].a_attr[k]; + } + else if (k === 'href' && m[dpc[i]].a_attr[k] === '#') { + m[dpc[i]].a_attr['href'] = t[c].a_attr['href']; + } + else if (k === 'class') { + m[dpc[i]].a_attr['class'] = t[c].a_attr['class'] + ' ' + m[dpc[i]].a_attr['class']; + } + } + } + } + } + m[$.jstree.root].type = $.jstree.root; + }, this)); + parent.bind.call(this); + }; + this.get_json = function (obj, options, flat) { + var i, j, + m = this._model.data, + opt = options ? $.extend(true, {}, options, {no_id:false}) : {}, + tmp = parent.get_json.call(this, obj, opt, flat); + if(tmp === false) { return false; } + if($.isArray(tmp)) { + for(i = 0, j = tmp.length; i < j; i++) { + tmp[i].type = tmp[i].id && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default"; + if(options && options.no_id) { + delete tmp[i].id; + if(tmp[i].li_attr && tmp[i].li_attr.id) { + delete tmp[i].li_attr.id; + } + if(tmp[i].a_attr && tmp[i].a_attr.id) { + delete tmp[i].a_attr.id; + } + } + } + } + else { + tmp.type = tmp.id && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default"; + if(options && options.no_id) { + tmp = this._delete_ids(tmp); + } + } + return tmp; + }; + this._delete_ids = function (tmp) { + if($.isArray(tmp)) { + for(var i = 0, j = tmp.length; i < j; i++) { + tmp[i] = this._delete_ids(tmp[i]); + } + return tmp; + } + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + if(tmp.a_attr && tmp.a_attr.id) { + delete tmp.a_attr.id; + } + if(tmp.children && $.isArray(tmp.children)) { + tmp.children = this._delete_ids(tmp.children); + } + return tmp; + }; + this.check = function (chk, obj, par, pos, more) { + if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var m = obj && obj.id ? (more && more.origin ? more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j; + m = m && m._model && m._model.data ? m._model.data : null; + switch(chk) { + case "create_node": + case "move_node": + case "copy_node": + if(chk !== 'move_node' || $.inArray(obj.id, par.children) === -1) { + tmp = this.get_rules(par); + if(tmp.max_children !== undefined && tmp.max_children !== -1 && tmp.max_children === par.children.length) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(tmp.valid_children !== undefined && tmp.valid_children !== -1 && $.inArray((obj.type || 'default'), tmp.valid_children) === -1) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(m && obj.children_d && obj.parents) { + d = 0; + for(i = 0, j = obj.children_d.length; i < j; i++) { + d = Math.max(d, m[obj.children_d[i]].parents.length); + } + d = d - obj.parents.length + 1; + } + if(d <= 0 || d === undefined) { d = 1; } + do { + if(tmp.max_depth !== undefined && tmp.max_depth !== -1 && tmp.max_depth < d) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + par = this.get_node(par.parent); + tmp = this.get_rules(par); + d++; + } while(par); + } + break; + } + return true; + }; + /** + * used to retrieve the type settings object for a node + * @name get_rules(obj) + * @param {mixed} obj the node to find the rules for + * @return {Object} + * @plugin types + */ + this.get_rules = function (obj) { + obj = this.get_node(obj); + if(!obj) { return false; } + var tmp = this.get_type(obj, true); + if(tmp.max_depth === undefined) { tmp.max_depth = -1; } + if(tmp.max_children === undefined) { tmp.max_children = -1; } + if(tmp.valid_children === undefined) { tmp.valid_children = -1; } + return tmp; + }; + /** + * used to retrieve the type string or settings object for a node + * @name get_type(obj [, rules]) + * @param {mixed} obj the node to find the rules for + * @param {Boolean} rules if set to `true` instead of a string the settings object will be returned + * @return {String|Object} + * @plugin types + */ + this.get_type = function (obj, rules) { + obj = this.get_node(obj); + return (!obj) ? false : ( rules ? $.extend({ 'type' : obj.type }, this.settings.types[obj.type]) : obj.type); + }; + /** + * used to change a node's type + * @name set_type(obj, type) + * @param {mixed} obj the node to change + * @param {String} type the new type + * @plugin types + */ + this.set_type = function (obj, type) { + var m = this._model.data, t, t1, t2, old_type, old_icon, k, d, a; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_type(obj[t1], type); + } + return true; + } + t = this.settings.types; + obj = this.get_node(obj); + if(!t[type] || !obj) { return false; } + d = this.get_node(obj, true); + if (d && d.length) { + a = d.children('.jstree-anchor'); + } + old_type = obj.type; + old_icon = this.get_icon(obj); + obj.type = type; + if(old_icon === true || !t[old_type] || (t[old_type].icon !== undefined && old_icon === t[old_type].icon)) { + this.set_icon(obj, t[type].icon !== undefined ? t[type].icon : true); + } + + // remove old type props + if(t[old_type] && t[old_type].li_attr !== undefined && typeof t[old_type].li_attr === 'object') { + for (k in t[old_type].li_attr) { + if (t[old_type].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (k === 'class') { + m[obj.id].li_attr['class'] = (m[obj.id].li_attr['class'] || '').replace(t[old_type].li_attr[k], ''); + if (d) { d.removeClass(t[old_type].li_attr[k]); } + } + else if (m[obj.id].li_attr[k] === t[old_type].li_attr[k]) { + m[obj.id].li_attr[k] = null; + if (d) { d.removeAttr(k); } + } + } + } + } + if(t[old_type] && t[old_type].a_attr !== undefined && typeof t[old_type].a_attr === 'object') { + for (k in t[old_type].a_attr) { + if (t[old_type].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (k === 'class') { + m[obj.id].a_attr['class'] = (m[obj.id].a_attr['class'] || '').replace(t[old_type].a_attr[k], ''); + if (a) { a.removeClass(t[old_type].a_attr[k]); } + } + else if (m[obj.id].a_attr[k] === t[old_type].a_attr[k]) { + if (k === 'href') { + m[obj.id].a_attr[k] = '#'; + if (a) { a.attr('href', '#'); } + } + else { + delete m[obj.id].a_attr[k]; + if (a) { a.removeAttr(k); } + } + } + } + } + } + + // add new props + if(t[type].li_attr !== undefined && typeof t[type].li_attr === 'object') { + for (k in t[type].li_attr) { + if (t[type].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[obj.id].li_attr[k] === undefined) { + m[obj.id].li_attr[k] = t[type].li_attr[k]; + if (d) { + if (k === 'class') { + d.addClass(t[type].li_attr[k]); + } + else { + d.attr(k, t[type].li_attr[k]); + } + } + } + else if (k === 'class') { + m[obj.id].li_attr['class'] = t[type].li_attr[k] + ' ' + m[obj.id].li_attr['class']; + if (d) { d.addClass(t[type].li_attr[k]); } + } + } + } + } + if(t[type].a_attr !== undefined && typeof t[type].a_attr === 'object') { + for (k in t[type].a_attr) { + if (t[type].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[obj.id].a_attr[k] === undefined) { + m[obj.id].a_attr[k] = t[type].a_attr[k]; + if (a) { + if (k === 'class') { + a.addClass(t[type].a_attr[k]); + } + else { + a.attr(k, t[type].a_attr[k]); + } + } + } + else if (k === 'href' && m[obj.id].a_attr[k] === '#') { + m[obj.id].a_attr['href'] = t[type].a_attr['href']; + if (a) { a.attr('href', t[type].a_attr['href']); } + } + else if (k === 'class') { + m[obj.id].a_attr['class'] = t[type].a_attr['class'] + ' ' + m[obj.id].a_attr['class']; + if (a) { a.addClass(t[type].a_attr[k]); } + } + } + } + } + + return true; + }; + }; + // include the types plugin by default + // $.jstree.defaults.plugins.push("types"); + + +/** + * ### Unique plugin + * + * Enforces that no nodes with the same name can coexist as siblings. + */ + + /** + * stores all defaults for the unique plugin + * @name $.jstree.defaults.unique + * @plugin unique + */ + $.jstree.defaults.unique = { + /** + * Indicates if the comparison should be case sensitive. Default is `false`. + * @name $.jstree.defaults.unique.case_sensitive + * @plugin unique + */ + case_sensitive : false, + /** + * A callback executed in the instance's scope when a new node is created and the name is already taken, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`. + * @name $.jstree.defaults.unique.duplicate + * @plugin unique + */ + duplicate : function (name, counter) { + return name + ' (' + counter + ')'; + } + }; + + $.jstree.plugins.unique = function (options, parent) { + this.check = function (chk, obj, par, pos, more) { + if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + if(!par || !par.children) { return true; } + var n = chk === "rename_node" ? pos : obj.text, + c = [], + s = this.settings.unique.case_sensitive, + m = this._model.data, i, j; + for(i = 0, j = par.children.length; i < j; i++) { + c.push(s ? m[par.children[i]].text : m[par.children[i]].text.toLowerCase()); + } + if(!s) { n = n.toLowerCase(); } + switch(chk) { + case "delete_node": + return true; + case "rename_node": + i = ($.inArray(n, c) === -1 || (obj.text && obj.text[ s ? 'toString' : 'toLowerCase']() === n)); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "create_node": + i = ($.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "copy_node": + i = ($.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "move_node": + i = ( (obj.parent === par.id && (!more || !more.is_multi)) || $.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + } + return true; + }; + this.create_node = function (par, node, pos, callback, is_loaded) { + if(!node || node.text === undefined) { + if(par === null) { + par = $.jstree.root; + } + par = this.get_node(par); + if(!par) { + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + } + pos = pos === undefined ? "last" : pos; + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + } + if(!node) { node = {}; } + var tmp, n, dpc, i, j, m = this._model.data, s = this.settings.unique.case_sensitive, cb = this.settings.unique.duplicate; + n = tmp = this.get_string('New node'); + dpc = []; + for(i = 0, j = par.children.length; i < j; i++) { + dpc.push(s ? m[par.children[i]].text : m[par.children[i]].text.toLowerCase()); + } + i = 1; + while($.inArray(s ? n : n.toLowerCase(), dpc) !== -1) { + n = cb.call(this, tmp, (++i)).toString(); + } + node.text = n; + } + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + }; + }; + + // include the unique plugin by default + // $.jstree.defaults.plugins.push("unique"); + + +/** + * ### Wholerow plugin + * + * Makes each node appear block level. Making selection easier. May cause slow down for large trees in old browsers. + */ + + var div = document.createElement('DIV'); + div.setAttribute('unselectable','on'); + div.setAttribute('role','presentation'); + div.className = 'jstree-wholerow'; + div.innerHTML = ' '; + $.jstree.plugins.wholerow = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this.element + .on('ready.jstree set_state.jstree', $.proxy(function () { + this.hide_dots(); + }, this)) + .on("init.jstree loading.jstree ready.jstree", $.proxy(function () { + //div.style.height = this._data.core.li_height + 'px'; + this.get_container_ul().addClass('jstree-wholerow-ul'); + }, this)) + .on("deselect_all.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + }, this)) + .on("changed.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + var tmp = false, i, j; + for(i = 0, j = data.selected.length; i < j; i++) { + tmp = this.get_node(data.selected[i], true); + if(tmp && tmp.length) { + tmp.children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + } + } + }, this)) + .on("open_node.jstree", $.proxy(function (e, data) { + this.get_node(data.node, true).find('.jstree-clicked').parent().children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + }, this)) + .on("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) { + if(e.type === "hover_node" && this.is_disabled(data.node)) { return; } + this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered'); + }, this)) + .on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) { + if (this._data.contextmenu) { + e.preventDefault(); + var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp); + } + }, this)) + /*! + .on("mousedown.jstree touchstart.jstree", ".jstree-wholerow", function (e) { + if(e.target === e.currentTarget) { + var a = $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor"); + e.target = a[0]; + a.trigger(e); + } + }) + */ + .on("click.jstree", ".jstree-wholerow", function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }) + .on("dblclick.jstree", ".jstree-wholerow", function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('dblclick', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }) + .on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }, this)) + .on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", $.proxy(function (e) { + e.stopImmediatePropagation(); + if(!this.is_disabled(e.currentTarget)) { + this.hover_node(e.currentTarget); + } + return false; + }, this)) + .on("mouseleave.jstree", ".jstree-node", $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }; + this.teardown = function () { + if(this.settings.wholerow) { + this.element.find(".jstree-wholerow").remove(); + } + parent.teardown.call(this); + }; + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + var tmp = div.cloneNode(true); + //tmp.style.height = this._data.core.li_height + 'px'; + if($.inArray(obj.id, this._data.core.selected) !== -1) { tmp.className += ' jstree-wholerow-clicked'; } + if(this._data.core.focused && this._data.core.focused === obj.id) { tmp.className += ' jstree-wholerow-hovered'; } + obj.insertBefore(tmp, obj.childNodes[0]); + } + return obj; + }; + }; + // include the wholerow plugin by default + // $.jstree.defaults.plugins.push("wholerow"); + if(document.registerElement && Object && Object.create) { + var proto = Object.create(HTMLElement.prototype); + proto.createdCallback = function () { + var c = { core : {}, plugins : [] }, i; + for(i in $.jstree.plugins) { + if($.jstree.plugins.hasOwnProperty(i) && this.attributes[i]) { + c.plugins.push(i); + if(this.getAttribute(i) && JSON.parse(this.getAttribute(i))) { + c[i] = JSON.parse(this.getAttribute(i)); + } + } + } + for(i in $.jstree.defaults.core) { + if($.jstree.defaults.core.hasOwnProperty(i) && this.attributes[i]) { + c.core[i] = JSON.parse(this.getAttribute(i)) || this.getAttribute(i); + } + } + $(this).jstree(c); + }; + // proto.attributeChangedCallback = function (name, previous, value) { }; + try { + document.registerElement("vakata-jstree", { prototype: proto }); + } catch(ignore) { } + } + +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/dist/jstree.min.js b/civicrm/bower_components/jstree/dist/jstree.min.js new file mode 100644 index 0000000000000000000000000000000000000000..24c420489eab32cf4f6f250d75f444f1b534020c --- /dev/null +++ b/civicrm/bower_components/jstree/dist/jstree.min.js @@ -0,0 +1,6 @@ +/*! jsTree - v3.3.3 - 2016-10-31 - (MIT) */ +!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a,b){"use strict";if(!a.jstree){var c=0,d=!1,e=!1,f=!1,g=[],h=a("script:last").attr("src"),i=window.document;a.jstree={version:"3.3.3",defaults:{plugins:[]},plugins:{},path:h&&-1!==h.indexOf("/")?h.replace(/\/[^\/]+$/,""):"",idregex:/[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,root:"#"},a.jstree.create=function(b,d){var e=new a.jstree.core(++c),f=d;return d=a.extend(!0,{},a.jstree.defaults,d),f&&f.plugins&&(d.plugins=f.plugins),a.each(d.plugins,function(a,b){"core"!==a&&(e=e.plugin(b,d[b]))}),a(b).data("jstree",e),e.init(b,d),e},a.jstree.destroy=function(){a(".jstree:jstree").jstree("destroy"),a(i).off(".jstree")},a.jstree.core=function(a){this._id=a,this._cnt=0,this._wrk=null,this._data={core:{themes:{name:!1,dots:!1,icons:!1,ellipsis:!1},selected:[],last_error:{},working:!1,worker_queue:[],focused:null}}},a.jstree.reference=function(b){var c=null,d=null;if(!b||!b.id||b.tagName&&b.nodeType||(b=b.id),!d||!d.length)try{d=a(b)}catch(e){}if(!d||!d.length)try{d=a("#"+b.replace(a.jstree.idregex,"\\$&"))}catch(e){}return d&&d.length&&(d=d.closest(".jstree")).length&&(d=d.data("jstree"))?c=d:a(".jstree").each(function(){var d=a(this).data("jstree");return d&&d._model.data[b]?(c=d,!1):void 0}),c},a.fn.jstree=function(c){var d="string"==typeof c,e=Array.prototype.slice.call(arguments,1),f=null;return c!==!0||this.length?(this.each(function(){var g=a.jstree.reference(this),h=d&&g?g[c]:null;return f=d&&h?h.apply(g,e):null,g||d||c!==b&&!a.isPlainObject(c)||a.jstree.create(this,c),(g&&!d||c===!0)&&(f=g||!1),null!==f&&f!==b?!1:void 0}),null!==f&&f!==b?f:this):!1},a.expr.pseudos.jstree=a.expr.createPseudo(function(c){return function(c){return a(c).hasClass("jstree")&&a(c).data("jstree")!==b}}),a.jstree.defaults.core={data:!1,strings:!1,check_callback:!1,error:a.noop,animation:200,multiple:!0,themes:{name:!1,url:!1,dir:!1,dots:!0,icons:!0,ellipsis:!1,stripes:!1,variant:!1,responsive:!1},expand_selected_onload:!0,worker:!0,force_text:!1,dblclick_toggle:!0},a.jstree.core.prototype={plugin:function(b,c){var d=a.jstree.plugins[b];return d?(this._data[b]={},d.prototype=this,new d(c,this)):this},init:function(b,c){this._model={data:{},changed:[],force_full_redraw:!1,redraw_timeout:!1,default_state:{loaded:!0,opened:!1,selected:!1,disabled:!1}},this._model.data[a.jstree.root]={id:a.jstree.root,parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}},this.element=a(b).addClass("jstree jstree-"+this._id),this.settings=c,this._data.core.ready=!1,this._data.core.loaded=!1,this._data.core.rtl="rtl"===this.element.css("direction"),this.element[this._data.core.rtl?"addClass":"removeClass"]("jstree-rtl"),this.element.attr("role","tree"),this.settings.core.multiple&&this.element.attr("aria-multiselectable",!0),this.element.attr("tabindex")||this.element.attr("tabindex","0"),this.bind(),this.trigger("init"),this._data.core.original_container_html=this.element.find(" > ul > li").clone(!0),this._data.core.original_container_html.find("li").addBack().contents().filter(function(){return 3===this.nodeType&&(!this.nodeValue||/^\s+$/.test(this.nodeValue))}).remove(),this.element.html("<ul class='jstree-container-ul jstree-children' role='group'><li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><i class='jstree-icon jstree-ocl'></i><a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>"+this.get_string("Loading ...")+"</a></li></ul>"),this.element.attr("aria-activedescendant","j"+this._id+"_loading"),this._data.core.li_height=this.get_container_ul().children("li").first().height()||24,this._data.core.node=this._create_prototype_node(),this.trigger("loading"),this.load_node(a.jstree.root)},destroy:function(a){if(this._wrk)try{window.URL.revokeObjectURL(this._wrk),this._wrk=null}catch(b){}a||this.element.empty(),this.teardown()},_create_prototype_node:function(){var a=i.createElement("LI"),b,c;return a.setAttribute("role","treeitem"),b=i.createElement("I"),b.className="jstree-icon jstree-ocl",b.setAttribute("role","presentation"),a.appendChild(b),b=i.createElement("A"),b.className="jstree-anchor",b.setAttribute("href","#"),b.setAttribute("tabindex","-1"),c=i.createElement("I"),c.className="jstree-icon jstree-themeicon",c.setAttribute("role","presentation"),b.appendChild(c),a.appendChild(b),b=c=null,a},teardown:function(){this.unbind(),this.element.removeClass("jstree").removeData("jstree").find("[class^='jstree']").addBack().attr("class",function(){return this.className.replace(/jstree[^ ]*|$/gi,"")}),this.element=null},bind:function(){var b="",c=null,d=0;this.element.on("dblclick.jstree",function(a){if(a.target.tagName&&"input"===a.target.tagName.toLowerCase())return!0;if(i.selection&&i.selection.empty)i.selection.empty();else if(window.getSelection){var b=window.getSelection();try{b.removeAllRanges(),b.collapse()}catch(c){}}}).on("mousedown.jstree",a.proxy(function(a){a.target===this.element[0]&&(a.preventDefault(),d=+new Date)},this)).on("mousedown.jstree",".jstree-ocl",function(a){a.preventDefault()}).on("click.jstree",".jstree-ocl",a.proxy(function(a){this.toggle_node(a.target)},this)).on("dblclick.jstree",".jstree-anchor",a.proxy(function(a){return a.target.tagName&&"input"===a.target.tagName.toLowerCase()?!0:void(this.settings.core.dblclick_toggle&&this.toggle_node(a.target))},this)).on("click.jstree",".jstree-anchor",a.proxy(function(b){b.preventDefault(),b.currentTarget!==i.activeElement&&a(b.currentTarget).focus(),this.activate_node(b.currentTarget,b)},this)).on("keydown.jstree",".jstree-anchor",a.proxy(function(b){if(b.target.tagName&&"input"===b.target.tagName.toLowerCase())return!0;if(32!==b.which&&13!==b.which&&(b.shiftKey||b.ctrlKey||b.altKey||b.metaKey))return!0;var c=null;switch(this._data.core.rtl&&(37===b.which?b.which=39:39===b.which&&(b.which=37)),b.which){case 32:b.ctrlKey&&(b.type="click",a(b.currentTarget).trigger(b));break;case 13:b.type="click",a(b.currentTarget).trigger(b);break;case 37:b.preventDefault(),this.is_open(b.currentTarget)?this.close_node(b.currentTarget):(c=this.get_parent(b.currentTarget),c&&c.id!==a.jstree.root&&this.get_node(c,!0).children(".jstree-anchor").focus());break;case 38:b.preventDefault(),c=this.get_prev_dom(b.currentTarget),c&&c.length&&c.children(".jstree-anchor").focus();break;case 39:b.preventDefault(),this.is_closed(b.currentTarget)?this.open_node(b.currentTarget,function(a){this.get_node(a,!0).children(".jstree-anchor").focus()}):this.is_open(b.currentTarget)&&(c=this.get_node(b.currentTarget,!0).children(".jstree-children")[0],c&&a(this._firstChild(c)).children(".jstree-anchor").focus());break;case 40:b.preventDefault(),c=this.get_next_dom(b.currentTarget),c&&c.length&&c.children(".jstree-anchor").focus();break;case 106:this.open_all();break;case 36:b.preventDefault(),c=this._firstChild(this.get_container_ul()[0]),c&&a(c).children(".jstree-anchor").filter(":visible").focus();break;case 35:b.preventDefault(),this.element.find(".jstree-anchor").filter(":visible").last().focus();break;case 113:b.preventDefault(),this.edit(b.currentTarget)}},this)).on("load_node.jstree",a.proxy(function(b,c){c.status&&(c.node.id!==a.jstree.root||this._data.core.loaded||(this._data.core.loaded=!0,this._firstChild(this.get_container_ul()[0])&&this.element.attr("aria-activedescendant",this._firstChild(this.get_container_ul()[0]).id),this.trigger("loaded")),this._data.core.ready||setTimeout(a.proxy(function(){if(this.element&&!this.get_container_ul().find(".jstree-loading").length){if(this._data.core.ready=!0,this._data.core.selected.length){if(this.settings.core.expand_selected_onload){var b=[],c,d;for(c=0,d=this._data.core.selected.length;d>c;c++)b=b.concat(this._model.data[this._data.core.selected[c]].parents);for(b=a.vakata.array_unique(b),c=0,d=b.length;d>c;c++)this.open_node(b[c],!1,0)}this.trigger("changed",{action:"ready",selected:this._data.core.selected})}this.trigger("ready")}},this),0))},this)).on("keypress.jstree",a.proxy(function(d){if(d.target.tagName&&"input"===d.target.tagName.toLowerCase())return!0;c&&clearTimeout(c),c=setTimeout(function(){b=""},500);var e=String.fromCharCode(d.which).toLowerCase(),f=this.element.find(".jstree-anchor").filter(":visible"),g=f.index(i.activeElement)||0,h=!1;if(b+=e,b.length>1){if(f.slice(g).each(a.proxy(function(c,d){return 0===a(d).text().toLowerCase().indexOf(b)?(a(d).focus(),h=!0,!1):void 0},this)),h)return;if(f.slice(0,g).each(a.proxy(function(c,d){return 0===a(d).text().toLowerCase().indexOf(b)?(a(d).focus(),h=!0,!1):void 0},this)),h)return}if(new RegExp("^"+e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+"+$").test(b)){if(f.slice(g+1).each(a.proxy(function(b,c){return a(c).text().toLowerCase().charAt(0)===e?(a(c).focus(),h=!0,!1):void 0},this)),h)return;if(f.slice(0,g+1).each(a.proxy(function(b,c){return a(c).text().toLowerCase().charAt(0)===e?(a(c).focus(),h=!0,!1):void 0},this)),h)return}},this)).on("init.jstree",a.proxy(function(){var a=this.settings.core.themes;this._data.core.themes.dots=a.dots,this._data.core.themes.stripes=a.stripes,this._data.core.themes.icons=a.icons,this._data.core.themes.ellipsis=a.ellipsis,this.set_theme(a.name||"default",a.url),this.set_theme_variant(a.variant)},this)).on("loading.jstree",a.proxy(function(){this[this._data.core.themes.dots?"show_dots":"hide_dots"](),this[this._data.core.themes.icons?"show_icons":"hide_icons"](),this[this._data.core.themes.stripes?"show_stripes":"hide_stripes"](),this[this._data.core.themes.ellipsis?"show_ellipsis":"hide_ellipsis"]()},this)).on("blur.jstree",".jstree-anchor",a.proxy(function(b){this._data.core.focused=null,a(b.currentTarget).filter(".jstree-hovered").mouseleave(),this.element.attr("tabindex","0")},this)).on("focus.jstree",".jstree-anchor",a.proxy(function(b){var c=this.get_node(b.currentTarget);c&&c.id&&(this._data.core.focused=c.id),this.element.find(".jstree-hovered").not(b.currentTarget).mouseleave(),a(b.currentTarget).mouseenter(),this.element.attr("tabindex","-1")},this)).on("focus.jstree",a.proxy(function(){if(+new Date-d>500&&!this._data.core.focused){d=0;var a=this.get_node(this.element.attr("aria-activedescendant"),!0);a&&a.find("> .jstree-anchor").focus()}},this)).on("mouseenter.jstree",".jstree-anchor",a.proxy(function(a){this.hover_node(a.currentTarget)},this)).on("mouseleave.jstree",".jstree-anchor",a.proxy(function(a){this.dehover_node(a.currentTarget)},this))},unbind:function(){this.element.off(".jstree"),a(i).off(".jstree-"+this._id)},trigger:function(a,b){b||(b={}),b.instance=this,this.element.triggerHandler(a.replace(".jstree","")+".jstree",b)},get_container:function(){return this.element},get_container_ul:function(){return this.element.children(".jstree-children").first()},get_string:function(b){var c=this.settings.core.strings;return a.isFunction(c)?c.call(this,b):c&&c[b]?c[b]:b},_firstChild:function(a){a=a?a.firstChild:null;while(null!==a&&1!==a.nodeType)a=a.nextSibling;return a},_nextSibling:function(a){a=a?a.nextSibling:null;while(null!==a&&1!==a.nodeType)a=a.nextSibling;return a},_previousSibling:function(a){a=a?a.previousSibling:null;while(null!==a&&1!==a.nodeType)a=a.previousSibling;return a},get_node:function(b,c){b&&b.id&&(b=b.id);var d;try{if(this._model.data[b])b=this._model.data[b];else if("string"==typeof b&&this._model.data[b.replace(/^#/,"")])b=this._model.data[b.replace(/^#/,"")];else if("string"==typeof b&&(d=a("#"+b.replace(a.jstree.idregex,"\\$&"),this.element)).length&&this._model.data[d.closest(".jstree-node").attr("id")])b=this._model.data[d.closest(".jstree-node").attr("id")];else if((d=a(b,this.element)).length&&this._model.data[d.closest(".jstree-node").attr("id")])b=this._model.data[d.closest(".jstree-node").attr("id")];else{if(!(d=a(b,this.element)).length||!d.hasClass("jstree"))return!1;b=this._model.data[a.jstree.root]}return c&&(b=b.id===a.jstree.root?this.element:a("#"+b.id.replace(a.jstree.idregex,"\\$&"),this.element)),b}catch(e){return!1}},get_path:function(b,c,d){if(b=b.parents?b:this.get_node(b),!b||b.id===a.jstree.root||!b.parents)return!1;var e,f,g=[];for(g.push(d?b.id:b.text),e=0,f=b.parents.length;f>e;e++)g.push(d?b.parents[e]:this.get_text(b.parents[e]));return g=g.reverse().slice(1),c?g.join(c):g},get_next_dom:function(b,c){var d;if(b=this.get_node(b,!0),b[0]===this.element[0]){d=this._firstChild(this.get_container_ul()[0]);while(d&&0===d.offsetHeight)d=this._nextSibling(d);return d?a(d):!1}if(!b||!b.length)return!1;if(c){d=b[0];do d=this._nextSibling(d);while(d&&0===d.offsetHeight);return d?a(d):!1}if(b.hasClass("jstree-open")){d=this._firstChild(b.children(".jstree-children")[0]);while(d&&0===d.offsetHeight)d=this._nextSibling(d);if(null!==d)return a(d)}d=b[0];do d=this._nextSibling(d);while(d&&0===d.offsetHeight);return null!==d?a(d):b.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first()},get_prev_dom:function(b,c){var d;if(b=this.get_node(b,!0),b[0]===this.element[0]){d=this.get_container_ul()[0].lastChild;while(d&&0===d.offsetHeight)d=this._previousSibling(d);return d?a(d):!1}if(!b||!b.length)return!1;if(c){d=b[0];do d=this._previousSibling(d);while(d&&0===d.offsetHeight);return d?a(d):!1}d=b[0];do d=this._previousSibling(d);while(d&&0===d.offsetHeight);if(null!==d){b=a(d);while(b.hasClass("jstree-open"))b=b.children(".jstree-children").first().children(".jstree-node:visible:last");return b}return d=b[0].parentNode.parentNode,d&&d.className&&-1!==d.className.indexOf("jstree-node")?a(d):!1},get_parent:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.parent:!1},get_children_dom:function(a){return a=this.get_node(a,!0),a[0]===this.element[0]?this.get_container_ul().children(".jstree-node"):a&&a.length?a.children(".jstree-children").children(".jstree-node"):!1},is_parent:function(a){return a=this.get_node(a),a&&(a.state.loaded===!1||a.children.length>0)},is_loaded:function(a){return a=this.get_node(a),a&&a.state.loaded},is_loading:function(a){return a=this.get_node(a),a&&a.state&&a.state.loading},is_open:function(a){return a=this.get_node(a),a&&a.state.opened},is_closed:function(a){return a=this.get_node(a),a&&this.is_parent(a)&&!a.state.opened},is_leaf:function(a){return!this.is_parent(a)},load_node:function(b,c){var d,e,f,g,h;if(a.isArray(b))return this._load_nodes(b.slice(),c),!0;if(b=this.get_node(b),!b)return c&&c.call(this,b,!1),!1;if(b.state.loaded){for(b.state.loaded=!1,f=0,g=b.parents.length;g>f;f++)this._model.data[b.parents[f]].children_d=a.vakata.array_filter(this._model.data[b.parents[f]].children_d,function(c){return-1===a.inArray(c,b.children_d)});for(d=0,e=b.children_d.length;e>d;d++)this._model.data[b.children_d[d]].state.selected&&(h=!0),delete this._model.data[b.children_d[d]];h&&(this._data.core.selected=a.vakata.array_filter(this._data.core.selected,function(c){return-1===a.inArray(c,b.children_d)})),b.children=[],b.children_d=[],h&&this.trigger("changed",{action:"load_node",node:b,selected:this._data.core.selected})}return b.state.failed=!1,b.state.loading=!0,this.get_node(b,!0).addClass("jstree-loading").attr("aria-busy",!0),this._load_node(b,a.proxy(function(a){b=this._model.data[b.id],b.state.loading=!1,b.state.loaded=a,b.state.failed=!b.state.loaded;var d=this.get_node(b,!0),e=0,f=0,g=this._model.data,h=!1;for(e=0,f=b.children.length;f>e;e++)if(g[b.children[e]]&&!g[b.children[e]].state.hidden){h=!0;break}b.state.loaded&&d&&d.length&&(d.removeClass("jstree-closed jstree-open jstree-leaf"),h?"#"!==b.id&&d.addClass(b.state.opened?"jstree-open":"jstree-closed"):d.addClass("jstree-leaf")),d.removeClass("jstree-loading").attr("aria-busy",!1),this.trigger("load_node",{node:b,status:a}),c&&c.call(this,b,a)},this)),!0},_load_nodes:function(a,b,c,d){var e=!0,f=function(){this._load_nodes(a,b,!0)},g=this._model.data,h,i,j=[];for(h=0,i=a.length;i>h;h++)g[a[h]]&&(!g[a[h]].state.loaded&&!g[a[h]].state.failed||!c&&d)&&(this.is_loading(a[h])||this.load_node(a[h],f),e=!1);if(e){for(h=0,i=a.length;i>h;h++)g[a[h]]&&g[a[h]].state.loaded&&j.push(a[h]);b&&!b.done&&(b.call(this,j),b.done=!0)}},load_all:function(b,c){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var d=[],e=this._model.data,f=e[b.id].children_d,g,h;for(b.state&&!b.state.loaded&&d.push(b.id),g=0,h=f.length;h>g;g++)e[f[g]]&&e[f[g]].state&&!e[f[g]].state.loaded&&d.push(f[g]);d.length?this._load_nodes(d,function(){this.load_all(b,c)}):(c&&c.call(this,b),this.trigger("load_all",{node:b}))},_load_node:function(b,c){var d=this.settings.core.data,e,f=function g(){return 3!==this.nodeType&&8!==this.nodeType};return d?a.isFunction(d)?d.call(this,b,a.proxy(function(d){d===!1?c.call(this,!1):this["string"==typeof d?"_append_html_data":"_append_json_data"](b,"string"==typeof d?a(a.parseHTML(d)).filter(f):d,function(a){c.call(this,a)})},this)):"object"==typeof d?d.url?(d=a.extend(!0,{},d),a.isFunction(d.url)&&(d.url=d.url.call(this,b)),a.isFunction(d.data)&&(d.data=d.data.call(this,b)),a.ajax(d).done(a.proxy(function(d,e,g){var h=g.getResponseHeader("Content-Type");return h&&-1!==h.indexOf("json")||"object"==typeof d?this._append_json_data(b,d,function(a){c.call(this,a)}):h&&-1!==h.indexOf("html")||"string"==typeof d?this._append_html_data(b,a(a.parseHTML(d)).filter(f),function(a){c.call(this,a)}):(this._data.core.last_error={error:"ajax",plugin:"core",id:"core_04",reason:"Could not load node",data:JSON.stringify({id:b.id,xhr:g})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1))},this)).fail(a.proxy(function(a){c.call(this,!1),this._data.core.last_error={error:"ajax",plugin:"core",id:"core_04",reason:"Could not load node",data:JSON.stringify({id:b.id,xhr:a})},this.settings.core.error.call(this,this._data.core.last_error)},this))):(e=a.isArray(d)||a.isPlainObject(d)?JSON.parse(JSON.stringify(d)):d,b.id===a.jstree.root?this._append_json_data(b,e,function(a){c.call(this,a)}):(this._data.core.last_error={error:"nodata",plugin:"core",id:"core_05",reason:"Could not load node",data:JSON.stringify({id:b.id})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1))):"string"==typeof d?b.id===a.jstree.root?this._append_html_data(b,a(a.parseHTML(d)).filter(f),function(a){c.call(this,a)}):(this._data.core.last_error={error:"nodata",plugin:"core",id:"core_06",reason:"Could not load node",data:JSON.stringify({id:b.id})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1)):c.call(this,!1):b.id===a.jstree.root?this._append_html_data(b,this._data.core.original_container_html.clone(!0),function(a){c.call(this,a)}):c.call(this,!1)},_node_changed:function(a){a=this.get_node(a),a&&this._model.changed.push(a.id)},_append_html_data:function(b,c,d){b=this.get_node(b),b.children=[],b.children_d=[];var e=c.is("ul")?c.children():c,f=b.id,g=[],h=[],i=this._model.data,j=i[f],k=this._data.core.selected.length,l,m,n;for(e.each(a.proxy(function(b,c){l=this._parse_model_from_html(a(c),f,j.parents.concat()),l&&(g.push(l),h.push(l),i[l].children_d.length&&(h=h.concat(i[l].children_d)))},this)),j.children=g,j.children_d=h,m=0,n=j.parents.length;n>m;m++)i[j.parents[m]].children_d=i[j.parents[m]].children_d.concat(h);this.trigger("model",{nodes:h,parent:f}),f!==a.jstree.root?(this._node_changed(f),this.redraw()):(this.get_container_ul().children(".jstree-initial-node").remove(),this.redraw(!0)),this._data.core.selected.length!==k&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),d.call(this,!0)},_append_json_data:function(b,c,d,e){if(null!==this.element){b=this.get_node(b),b.children=[],b.children_d=[],c.d&&(c=c.d,"string"==typeof c&&(c=JSON.parse(c))),a.isArray(c)||(c=[c]);var f=null,g={df:this._model.default_state,dat:c,par:b.id,m:this._model.data,t_id:this._id,t_cnt:this._cnt,sel:this._data.core.selected},h=function(a,b){a.data&&(a=a.data);var c=a.dat,d=a.par,e=[],f=[],g=[],h=a.df,i=a.t_id,j=a.t_cnt,k=a.m,l=k[d],m=a.sel,n,o,p,q,r=function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=a.id.toString(),f,i,j,l,m={id:e,text:a.text||"",icon:a.icon!==b?a.icon:!0,parent:c,parents:d,children:a.children||[],children_d:a.children_d||[],data:a.data,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in h)h.hasOwnProperty(f)&&(m.state[f]=h[f]);if(a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(m.icon=a.data.jstree.icon),(m.icon===b||null===m.icon||""===m.icon)&&(m.icon=!0),a&&a.data&&(m.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(m.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(m.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(m.li_attr[f]=a.li_attr[f]);if(m.li_attr.id||(m.li_attr.id=e),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(m.a_attr[f]=a.a_attr[f]);for(a&&a.children&&a.children===!0&&(m.state.loaded=!1,m.children=[],m.children_d=[]),k[m.id]=m,f=0,i=m.children.length;i>f;f++)j=r(k[m.children[f]],m.id,d),l=k[j],m.children_d.push(j),l.children_d.length&&(m.children_d=m.children_d.concat(l.children_d));return delete a.data,delete a.children,k[m.id].original=a,m.state.selected&&g.push(m.id),m.id},s=function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=!1,f,l,m,n,o;do e="j"+i+"_"+ ++j;while(k[e]);o={id:!1,text:"string"==typeof a?a:"",icon:"object"==typeof a&&a.icon!==b?a.icon:!0,parent:c,parents:d,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in h)h.hasOwnProperty(f)&&(o.state[f]=h[f]);if(a&&a.id&&(o.id=a.id.toString()),a&&a.text&&(o.text=a.text),a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(o.icon=a.data.jstree.icon),(o.icon===b||null===o.icon||""===o.icon)&&(o.icon=!0),a&&a.data&&(o.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(o.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(o.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(o.li_attr[f]=a.li_attr[f]);if(o.li_attr.id&&!o.id&&(o.id=o.li_attr.id.toString()),o.id||(o.id=e),o.li_attr.id||(o.li_attr.id=o.id),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(o.a_attr[f]=a.a_attr[f]);if(a&&a.children&&a.children.length){for(f=0,l=a.children.length;l>f;f++)m=s(a.children[f],o.id,d),n=k[m],o.children.push(m),n.children_d.length&&(o.children_d=o.children_d.concat(n.children_d));o.children_d=o.children_d.concat(o.children)}return a&&a.children&&a.children===!0&&(o.state.loaded=!1,o.children=[],o.children_d=[]),delete a.data,delete a.children,o.original=a,k[o.id]=o,o.state.selected&&g.push(o.id),o.id};if(c.length&&c[0].id!==b&&c[0].parent!==b){for(o=0,p=c.length;p>o;o++)c[o].children||(c[o].children=[]),k[c[o].id.toString()]=c[o];for(o=0,p=c.length;p>o;o++)k[c[o].parent.toString()].children.push(c[o].id.toString()),l.children_d.push(c[o].id.toString());for(o=0,p=l.children.length;p>o;o++)n=r(k[l.children[o]],d,l.parents.concat()),f.push(n),k[n].children_d.length&&(f=f.concat(k[n].children_d));for(o=0,p=l.parents.length;p>o;o++)k[l.parents[o]].children_d=k[l.parents[o]].children_d.concat(f);q={cnt:j,mod:k,sel:m,par:d,dpc:f,add:g}}else{for(o=0,p=c.length;p>o;o++)n=s(c[o],d,l.parents.concat()),n&&(e.push(n),f.push(n),k[n].children_d.length&&(f=f.concat(k[n].children_d)));for(l.children=e,l.children_d=f,o=0,p=l.parents.length;p>o;o++)k[l.parents[o]].children_d=k[l.parents[o]].children_d.concat(f);q={cnt:j,mod:k,sel:m,par:d,dpc:f,add:g}}return"undefined"!=typeof window&&"undefined"!=typeof window.document?q:void postMessage(q)},i=function(b,c){if(null!==this.element){this._cnt=b.cnt;var e,f=this._model.data;for(e in f)f.hasOwnProperty(e)&&f[e].state&&f[e].state.loading&&b.mod[e]&&(b.mod[e].state.loading=!0);if(this._model.data=b.mod,c){var g,h=b.add,i=b.sel,j=this._data.core.selected.slice();if(f=this._model.data,i.length!==j.length||a.vakata.array_unique(i.concat(j)).length!==i.length){for(e=0,g=i.length;g>e;e++)-1===a.inArray(i[e],h)&&-1===a.inArray(i[e],j)&&(f[i[e]].state.selected=!1);for(e=0,g=j.length;g>e;e++)-1===a.inArray(j[e],i)&&(f[j[e]].state.selected=!0)}}b.add.length&&(this._data.core.selected=this._data.core.selected.concat(b.add)),this.trigger("model",{nodes:b.dpc,parent:b.par}),b.par!==a.jstree.root?(this._node_changed(b.par),this.redraw()):this.redraw(!0),b.add.length&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),d.call(this,!0)}};if(this.settings.core.worker&&window.Blob&&window.URL&&window.Worker)try{null===this._wrk&&(this._wrk=window.URL.createObjectURL(new window.Blob(["self.onmessage = "+h.toString()],{type:"text/javascript"}))),!this._data.core.working||e?(this._data.core.working=!0,f=new window.Worker(this._wrk),f.onmessage=a.proxy(function(a){i.call(this,a.data,!0);try{f.terminate(),f=null}catch(b){}this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1},this),g.par?f.postMessage(g):this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1):this._data.core.worker_queue.push([b,c,d,!0])}catch(j){i.call(this,h(g),!1),this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1}else i.call(this,h(g),!1)}},_parse_model_from_html:function(c,d,e){e=e?[].concat(e):[],d&&e.unshift(d);var f,g,h=this._model.data,i={id:!1,text:!1,icon:!0,parent:d,parents:e,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1},j,k,l;for(j in this._model.default_state)this._model.default_state.hasOwnProperty(j)&&(i.state[j]=this._model.default_state[j]);if(k=a.vakata.attributes(c,!0),a.each(k,function(b,c){return c=a.trim(c),c.length?(i.li_attr[b]=c,void("id"===b&&(i.id=c.toString()))):!0}),k=c.children("a").first(),k.length&&(k=a.vakata.attributes(k,!0),a.each(k,function(b,c){c=a.trim(c),c.length&&(i.a_attr[b]=c)})),k=c.children("a").first().length?c.children("a").first().clone():c.clone(),k.children("ins, i, ul").remove(),k=k.html(),k=a("<div />").html(k),i.text=this.settings.core.force_text?k.text():k.html(),k=c.data(),i.data=k?a.extend(!0,{},k):null,i.state.opened=c.hasClass("jstree-open"),i.state.selected=c.children("a").hasClass("jstree-clicked"),i.state.disabled=c.children("a").hasClass("jstree-disabled"),i.data&&i.data.jstree)for(j in i.data.jstree)i.data.jstree.hasOwnProperty(j)&&(i.state[j]=i.data.jstree[j]);k=c.children("a").children(".jstree-themeicon"),k.length&&(i.icon=k.hasClass("jstree-themeicon-hidden")?!1:k.attr("rel")),i.state.icon!==b&&(i.icon=i.state.icon),(i.icon===b||null===i.icon||""===i.icon)&&(i.icon=!0),k=c.children("ul").children("li");do l="j"+this._id+"_"+ ++this._cnt;while(h[l]);return i.id=i.li_attr.id?i.li_attr.id.toString():l,k.length?(k.each(a.proxy(function(b,c){f=this._parse_model_from_html(a(c),i.id,e),g=this._model.data[f],i.children.push(f),g.children_d.length&&(i.children_d=i.children_d.concat(g.children_d))},this)),i.children_d=i.children_d.concat(i.children)):c.hasClass("jstree-closed")&&(i.state.loaded=!1),i.li_attr["class"]&&(i.li_attr["class"]=i.li_attr["class"].replace("jstree-closed","").replace("jstree-open","")),i.a_attr["class"]&&(i.a_attr["class"]=i.a_attr["class"].replace("jstree-clicked","").replace("jstree-disabled","")),h[i.id]=i,i.state.selected&&this._data.core.selected.push(i.id),i.id},_parse_model_from_flat_json:function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=a.id.toString(),f=this._model.data,g=this._model.default_state,h,i,j,k,l={id:e,text:a.text||"",icon:a.icon!==b?a.icon:!0,parent:c,parents:d,children:a.children||[],children_d:a.children_d||[],data:a.data,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(h in g)g.hasOwnProperty(h)&&(l.state[h]=g[h]);if(a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(l.icon=a.data.jstree.icon),(l.icon===b||null===l.icon||""===l.icon)&&(l.icon=!0),a&&a.data&&(l.data=a.data,a.data.jstree))for(h in a.data.jstree)a.data.jstree.hasOwnProperty(h)&&(l.state[h]=a.data.jstree[h]);if(a&&"object"==typeof a.state)for(h in a.state)a.state.hasOwnProperty(h)&&(l.state[h]=a.state[h]);if(a&&"object"==typeof a.li_attr)for(h in a.li_attr)a.li_attr.hasOwnProperty(h)&&(l.li_attr[h]=a.li_attr[h]);if(l.li_attr.id||(l.li_attr.id=e),a&&"object"==typeof a.a_attr)for(h in a.a_attr)a.a_attr.hasOwnProperty(h)&&(l.a_attr[h]=a.a_attr[h]);for(a&&a.children&&a.children===!0&&(l.state.loaded=!1,l.children=[],l.children_d=[]),f[l.id]=l,h=0,i=l.children.length;i>h;h++)j=this._parse_model_from_flat_json(f[l.children[h]],l.id,d),k=f[j],l.children_d.push(j),k.children_d.length&&(l.children_d=l.children_d.concat(k.children_d));return delete a.data,delete a.children,f[l.id].original=a,l.state.selected&&this._data.core.selected.push(l.id),l.id},_parse_model_from_json:function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=!1,f,g,h,i,j=this._model.data,k=this._model.default_state,l;do e="j"+this._id+"_"+ ++this._cnt;while(j[e]);l={id:!1,text:"string"==typeof a?a:"",icon:"object"==typeof a&&a.icon!==b?a.icon:!0,parent:c,parents:d,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in k)k.hasOwnProperty(f)&&(l.state[f]=k[f]);if(a&&a.id&&(l.id=a.id.toString()),a&&a.text&&(l.text=a.text),a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(l.icon=a.data.jstree.icon),(l.icon===b||null===l.icon||""===l.icon)&&(l.icon=!0),a&&a.data&&(l.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(l.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(l.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(l.li_attr[f]=a.li_attr[f]);if(l.li_attr.id&&!l.id&&(l.id=l.li_attr.id.toString()),l.id||(l.id=e),l.li_attr.id||(l.li_attr.id=l.id),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(l.a_attr[f]=a.a_attr[f]);if(a&&a.children&&a.children.length){for(f=0,g=a.children.length;g>f;f++)h=this._parse_model_from_json(a.children[f],l.id,d),i=j[h],l.children.push(h),i.children_d.length&&(l.children_d=l.children_d.concat(i.children_d));l.children_d=l.children_d.concat(l.children)}return a&&a.children&&a.children===!0&&(l.state.loaded=!1,l.children=[],l.children_d=[]),delete a.data,delete a.children,l.original=a,j[l.id]=l,l.state.selected&&this._data.core.selected.push(l.id),l.id},_redraw:function(){var b=this._model.force_full_redraw?this._model.data[a.jstree.root].children.concat([]):this._model.changed.concat([]),c=i.createElement("UL"),d,e,f,g=this._data.core.focused;for(e=0,f=b.length;f>e;e++)d=this.redraw_node(b[e],!0,this._model.force_full_redraw),d&&this._model.force_full_redraw&&c.appendChild(d);this._model.force_full_redraw&&(c.className=this.get_container_ul()[0].className,c.setAttribute("role","group"),this.element.empty().append(c)),null!==g&&(d=this.get_node(g,!0),d&&d.length&&d.children(".jstree-anchor")[0]!==i.activeElement?d.children(".jstree-anchor").focus():this._data.core.focused=null),this._model.force_full_redraw=!1,this._model.changed=[],this.trigger("redraw",{nodes:b})},redraw:function(a){a&&(this._model.force_full_redraw=!0),this._redraw()},draw_children:function(b){var c=this.get_node(b),d=!1,e=!1,f=!1,g=i;if(!c)return!1;if(c.id===a.jstree.root)return this.redraw(!0);if(b=this.get_node(b,!0),!b||!b.length)return!1;if(b.children(".jstree-children").remove(),b=b[0],c.children.length&&c.state.loaded){for(f=g.createElement("UL"),f.setAttribute("role","group"),f.className="jstree-children",d=0,e=c.children.length;e>d;d++)f.appendChild(this.redraw_node(c.children[d],!0,!0));b.appendChild(f)}},redraw_node:function(b,c,d,e){var f=this.get_node(b),g=!1,h=!1,j=!1,k=!1,l=!1,m=!1,n="",o=i,p=this._model.data,q=!1,r=!1,s=null,t=0,u=0,v=!1,w=!1; +if(!f)return!1;if(f.id===a.jstree.root)return this.redraw(!0);if(c=c||0===f.children.length,b=i.querySelector?this.element[0].querySelector("#"+(-1!=="0123456789".indexOf(f.id[0])?"\\3"+f.id[0]+" "+f.id.substr(1).replace(a.jstree.idregex,"\\$&"):f.id.replace(a.jstree.idregex,"\\$&"))):i.getElementById(f.id))b=a(b),d||(g=b.parent().parent()[0],g===this.element[0]&&(g=null),h=b.index()),c||!f.children.length||b.children(".jstree-children").length||(c=!0),c||(j=b.children(".jstree-children")[0]),q=b.children(".jstree-anchor")[0]===i.activeElement,b.remove();else if(c=!0,!d){if(g=f.parent!==a.jstree.root?a("#"+f.parent.replace(a.jstree.idregex,"\\$&"),this.element)[0]:null,!(null===g||g&&p[f.parent].state.opened))return!1;h=a.inArray(f.id,null===g?p[a.jstree.root].children:p[f.parent].children)}b=this._data.core.node.cloneNode(!0),n="jstree-node ";for(k in f.li_attr)if(f.li_attr.hasOwnProperty(k)){if("id"===k)continue;"class"!==k?b.setAttribute(k,f.li_attr[k]):n+=f.li_attr[k]}for(f.a_attr.id||(f.a_attr.id=f.id+"_anchor"),b.setAttribute("aria-selected",!!f.state.selected),b.setAttribute("aria-level",f.parents.length),b.setAttribute("aria-labelledby",f.a_attr.id),f.state.disabled&&b.setAttribute("aria-disabled",!0),k=0,l=f.children.length;l>k;k++)if(!p[f.children[k]].state.hidden){v=!0;break}if(null!==f.parent&&p[f.parent]&&!f.state.hidden&&(k=a.inArray(f.id,p[f.parent].children),w=f.id,-1!==k))for(k++,l=p[f.parent].children.length;l>k;k++)if(p[p[f.parent].children[k]].state.hidden||(w=p[f.parent].children[k]),w!==f.id)break;f.state.hidden&&(n+=" jstree-hidden"),f.state.loaded&&!v?n+=" jstree-leaf":(n+=f.state.opened&&f.state.loaded?" jstree-open":" jstree-closed",b.setAttribute("aria-expanded",f.state.opened&&f.state.loaded)),w===f.id&&(n+=" jstree-last"),b.id=f.id,b.className=n,n=(f.state.selected?" jstree-clicked":"")+(f.state.disabled?" jstree-disabled":"");for(l in f.a_attr)if(f.a_attr.hasOwnProperty(l)){if("href"===l&&"#"===f.a_attr[l])continue;"class"!==l?b.childNodes[1].setAttribute(l,f.a_attr[l]):n+=" "+f.a_attr[l]}if(n.length&&(b.childNodes[1].className="jstree-anchor "+n),(f.icon&&f.icon!==!0||f.icon===!1)&&(f.icon===!1?b.childNodes[1].childNodes[0].className+=" jstree-themeicon-hidden":-1===f.icon.indexOf("/")&&-1===f.icon.indexOf(".")?b.childNodes[1].childNodes[0].className+=" "+f.icon+" jstree-themeicon-custom":(b.childNodes[1].childNodes[0].style.backgroundImage='url("'+f.icon+'")',b.childNodes[1].childNodes[0].style.backgroundPosition="center center",b.childNodes[1].childNodes[0].style.backgroundSize="auto",b.childNodes[1].childNodes[0].className+=" jstree-themeicon-custom")),this.settings.core.force_text?b.childNodes[1].appendChild(o.createTextNode(f.text)):b.childNodes[1].innerHTML+=f.text,c&&f.children.length&&(f.state.opened||e)&&f.state.loaded){for(m=o.createElement("UL"),m.setAttribute("role","group"),m.className="jstree-children",k=0,l=f.children.length;l>k;k++)m.appendChild(this.redraw_node(f.children[k],c,!0));b.appendChild(m)}if(j&&b.appendChild(j),!d){for(g||(g=this.element[0]),k=0,l=g.childNodes.length;l>k;k++)if(g.childNodes[k]&&g.childNodes[k].className&&-1!==g.childNodes[k].className.indexOf("jstree-children")){s=g.childNodes[k];break}s||(s=o.createElement("UL"),s.setAttribute("role","group"),s.className="jstree-children",g.appendChild(s)),g=s,h<g.childNodes.length?g.insertBefore(b,g.childNodes[h]):g.appendChild(b),q&&(t=this.element[0].scrollTop,u=this.element[0].scrollLeft,b.childNodes[1].focus(),this.element[0].scrollTop=t,this.element[0].scrollLeft=u)}return f.state.opened&&!f.state.loaded&&(f.state.opened=!1,setTimeout(a.proxy(function(){this.open_node(f.id,!1,0)},this),0)),b},open_node:function(c,d,e){var f,g,h,i;if(a.isArray(c)){for(c=c.slice(),f=0,g=c.length;g>f;f++)this.open_node(c[f],d,e);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?(e=e===b?this.settings.core.animation:e,this.is_closed(c)?this.is_loaded(c)?(h=this.get_node(c,!0),i=this,h.length&&(e&&h.children(".jstree-children").length&&h.children(".jstree-children").stop(!0,!0),c.children.length&&!this._firstChild(h.children(".jstree-children")[0])&&this.draw_children(c),e?(this.trigger("before_open",{node:c}),h.children(".jstree-children").css("display","none").end().removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded",!0).children(".jstree-children").stop(!0,!0).slideDown(e,function(){this.style.display="",i.element&&i.trigger("after_open",{node:c})})):(this.trigger("before_open",{node:c}),h[0].className=h[0].className.replace("jstree-closed","jstree-open"),h[0].setAttribute("aria-expanded",!0))),c.state.opened=!0,d&&d.call(this,c,!0),h.length||this.trigger("before_open",{node:c}),this.trigger("open_node",{node:c}),e&&h.length||this.trigger("after_open",{node:c}),!0):this.is_loading(c)?setTimeout(a.proxy(function(){this.open_node(c,d,e)},this),500):void this.load_node(c,function(a,b){return b?this.open_node(a,d,e):d?d.call(this,a,!1):!1}):(d&&d.call(this,c,!1),!1)):!1},_open_to:function(b){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var c,d,e=b.parents;for(c=0,d=e.length;d>c;c+=1)c!==a.jstree.root&&this.open_node(e[c],!1,0);return a("#"+b.id.replace(a.jstree.idregex,"\\$&"),this.element)},close_node:function(c,d){var e,f,g,h;if(a.isArray(c)){for(c=c.slice(),e=0,f=c.length;f>e;e++)this.close_node(c[e],d);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?this.is_closed(c)?!1:(d=d===b?this.settings.core.animation:d,g=this,h=this.get_node(c,!0),c.state.opened=!1,this.trigger("close_node",{node:c}),void(h.length?d?h.children(".jstree-children").attr("style","display:block !important").end().removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded",!1).children(".jstree-children").stop(!0,!0).slideUp(d,function(){this.style.display="",h.children(".jstree-children").remove(),g.element&&g.trigger("after_close",{node:c})}):(h[0].className=h[0].className.replace("jstree-open","jstree-closed"),h.attr("aria-expanded",!1).children(".jstree-children").remove(),this.trigger("after_close",{node:c})):this.trigger("after_close",{node:c}))):!1},toggle_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.toggle_node(b[c]);return!0}return this.is_closed(b)?this.open_node(b):this.is_open(b)?this.close_node(b):void 0},open_all:function(b,c,d){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var e=b.id===a.jstree.root?this.get_container_ul():this.get_node(b,!0),f,g,h;if(!e.length){for(f=0,g=b.children_d.length;g>f;f++)this.is_closed(this._model.data[b.children_d[f]])&&(this._model.data[b.children_d[f]].state.opened=!0);return this.trigger("open_all",{node:b})}d=d||e,h=this,e=this.is_closed(b)?e.find(".jstree-closed").addBack():e.find(".jstree-closed"),e.each(function(){h.open_node(this,function(a,b){b&&this.is_parent(a)&&this.open_all(a,c,d)},c||0)}),0===d.find(".jstree-closed").length&&this.trigger("open_all",{node:this.get_node(d)})},close_all:function(b,c){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var d=b.id===a.jstree.root?this.get_container_ul():this.get_node(b,!0),e=this,f,g;for(d.length&&(d=this.is_open(b)?d.find(".jstree-open").addBack():d.find(".jstree-open"),a(d.get().reverse()).each(function(){e.close_node(this,c||0)})),f=0,g=b.children_d.length;g>f;f++)this._model.data[b.children_d[f]].state.opened=!1;this.trigger("close_all",{node:b})},is_disabled:function(a){return a=this.get_node(a),a&&a.state&&a.state.disabled},enable_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.enable_node(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.state.disabled=!1,this.get_node(b,!0).children(".jstree-anchor").removeClass("jstree-disabled").attr("aria-disabled",!1),void this.trigger("enable_node",{node:b})):!1},disable_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.disable_node(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.state.disabled=!0,this.get_node(b,!0).children(".jstree-anchor").addClass("jstree-disabled").attr("aria-disabled",!0),void this.trigger("disable_node",{node:b})):!1},is_hidden:function(a){return a=this.get_node(a),a.state.hidden===!0},hide_node:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.hide_node(b[d],!0);return c||this.redraw(),!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?void(b.state.hidden||(b.state.hidden=!0,this._node_changed(b.parent),c||this.redraw(),this.trigger("hide_node",{node:b}))):!1},show_node:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.show_node(b[d],!0);return c||this.redraw(),!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?void(b.state.hidden&&(b.state.hidden=!1,this._node_changed(b.parent),c||this.redraw(),this.trigger("show_node",{node:b}))):!1},hide_all:function(b){var c,d=this._model.data,e=[];for(c in d)d.hasOwnProperty(c)&&c!==a.jstree.root&&!d[c].state.hidden&&(d[c].state.hidden=!0,e.push(c));return this._model.force_full_redraw=!0,b||this.redraw(),this.trigger("hide_all",{nodes:e}),e},show_all:function(b){var c,d=this._model.data,e=[];for(c in d)d.hasOwnProperty(c)&&c!==a.jstree.root&&d[c].state.hidden&&(d[c].state.hidden=!1,e.push(c));return this._model.force_full_redraw=!0,b||this.redraw(),this.trigger("show_all",{nodes:e}),e},activate_node:function(a,c){if(this.is_disabled(a))return!1;if(c&&"object"==typeof c||(c={}),this._data.core.last_clicked=this._data.core.last_clicked&&this._data.core.last_clicked.id!==b?this.get_node(this._data.core.last_clicked.id):null,this._data.core.last_clicked&&!this._data.core.last_clicked.state.selected&&(this._data.core.last_clicked=null),!this._data.core.last_clicked&&this._data.core.selected.length&&(this._data.core.last_clicked=this.get_node(this._data.core.selected[this._data.core.selected.length-1])),this.settings.core.multiple&&(c.metaKey||c.ctrlKey||c.shiftKey)&&(!c.shiftKey||this._data.core.last_clicked&&this.get_parent(a)&&this.get_parent(a)===this._data.core.last_clicked.parent))if(c.shiftKey){var d=this.get_node(a).id,e=this._data.core.last_clicked.id,f=this.get_node(this._data.core.last_clicked.parent).children,g=!1,h,i;for(h=0,i=f.length;i>h;h+=1)f[h]===d&&(g=!g),f[h]===e&&(g=!g),this.is_disabled(f[h])||!g&&f[h]!==d&&f[h]!==e?this.deselect_node(f[h],!0,c):this.is_hidden(f[h])||this.select_node(f[h],!0,!1,c);this.trigger("changed",{action:"select_node",node:this.get_node(a),selected:this._data.core.selected,event:c})}else this.is_selected(a)?this.deselect_node(a,!1,c):this.select_node(a,!1,!1,c);else!this.settings.core.multiple&&(c.metaKey||c.ctrlKey||c.shiftKey)&&this.is_selected(a)?this.deselect_node(a,!1,c):(this.deselect_all(!0),this.select_node(a,!1,!1,c),this._data.core.last_clicked=this.get_node(a));this.trigger("activate_node",{node:this.get_node(a),event:c})},hover_node:function(a){if(a=this.get_node(a,!0),!a||!a.length||a.children(".jstree-hovered").length)return!1;var b=this.element.find(".jstree-hovered"),c=this.element;b&&b.length&&this.dehover_node(b),a.children(".jstree-anchor").addClass("jstree-hovered"),this.trigger("hover_node",{node:this.get_node(a)}),setTimeout(function(){c.attr("aria-activedescendant",a[0].id)},0)},dehover_node:function(a){return a=this.get_node(a,!0),a&&a.length&&a.children(".jstree-hovered").length?(a.children(".jstree-anchor").removeClass("jstree-hovered"),void this.trigger("dehover_node",{node:this.get_node(a)})):!1},select_node:function(b,c,d,e){var f,g,h,i;if(a.isArray(b)){for(b=b.slice(),g=0,h=b.length;h>g;g++)this.select_node(b[g],c,d,e);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=this.get_node(b,!0),void(b.state.selected||(b.state.selected=!0,this._data.core.selected.push(b.id),d||(f=this._open_to(b)),f&&f.length&&f.attr("aria-selected",!0).children(".jstree-anchor").addClass("jstree-clicked"),this.trigger("select_node",{node:b,selected:this._data.core.selected,event:e}),c||this.trigger("changed",{action:"select_node",node:b,selected:this._data.core.selected,event:e})))):!1},deselect_node:function(b,c,d){var e,f,g;if(a.isArray(b)){for(b=b.slice(),e=0,f=b.length;f>e;e++)this.deselect_node(b[e],c,d);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(g=this.get_node(b,!0),void(b.state.selected&&(b.state.selected=!1,this._data.core.selected=a.vakata.array_remove_item(this._data.core.selected,b.id),g.length&&g.attr("aria-selected",!1).children(".jstree-anchor").removeClass("jstree-clicked"),this.trigger("deselect_node",{node:b,selected:this._data.core.selected,event:d}),c||this.trigger("changed",{action:"deselect_node",node:b,selected:this._data.core.selected,event:d})))):!1},select_all:function(b){var c=this._data.core.selected.concat([]),d,e;for(this._data.core.selected=this._model.data[a.jstree.root].children_d.concat(),d=0,e=this._data.core.selected.length;e>d;d++)this._model.data[this._data.core.selected[d]]&&(this._model.data[this._data.core.selected[d]].state.selected=!0);this.redraw(!0),this.trigger("select_all",{selected:this._data.core.selected}),b||this.trigger("changed",{action:"select_all",selected:this._data.core.selected,old_selection:c})},deselect_all:function(a){var b=this._data.core.selected.concat([]),c,d;for(c=0,d=this._data.core.selected.length;d>c;c++)this._model.data[this._data.core.selected[c]]&&(this._model.data[this._data.core.selected[c]].state.selected=!1);this._data.core.selected=[],this.element.find(".jstree-clicked").removeClass("jstree-clicked").parent().attr("aria-selected",!1),this.trigger("deselect_all",{selected:this._data.core.selected,node:b}),a||this.trigger("changed",{action:"deselect_all",selected:this._data.core.selected,old_selection:b})},is_selected:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.state.selected:!1},get_selected:function(b){return b?a.map(this._data.core.selected,a.proxy(function(a){return this.get_node(a)},this)):this._data.core.selected.slice()},get_top_selected:function(b){var c=this.get_selected(!0),d={},e,f,g,h;for(e=0,f=c.length;f>e;e++)d[c[e].id]=c[e];for(e=0,f=c.length;f>e;e++)for(g=0,h=c[e].children_d.length;h>g;g++)d[c[e].children_d[g]]&&delete d[c[e].children_d[g]];c=[];for(e in d)d.hasOwnProperty(e)&&c.push(e);return b?a.map(c,a.proxy(function(a){return this.get_node(a)},this)):c},get_bottom_selected:function(b){var c=this.get_selected(!0),d=[],e,f;for(e=0,f=c.length;f>e;e++)c[e].children.length||d.push(c[e].id);return b?a.map(d,a.proxy(function(a){return this.get_node(a)},this)):d},get_state:function(){var b={core:{open:[],scroll:{left:this.element.scrollLeft(),top:this.element.scrollTop()},selected:[]}},c;for(c in this._model.data)this._model.data.hasOwnProperty(c)&&c!==a.jstree.root&&(this._model.data[c].state.opened&&b.core.open.push(c),this._model.data[c].state.selected&&b.core.selected.push(c));return b},set_state:function(c,d){if(c){if(c.core){var e,f,g,h,i;if(c.core.open)return a.isArray(c.core.open)&&c.core.open.length?this._load_nodes(c.core.open,function(a){this.open_node(a,!1,0),delete c.core.open,this.set_state(c,d)}):(delete c.core.open,this.set_state(c,d)),!1;if(c.core.scroll)return c.core.scroll&&c.core.scroll.left!==b&&this.element.scrollLeft(c.core.scroll.left),c.core.scroll&&c.core.scroll.top!==b&&this.element.scrollTop(c.core.scroll.top),delete c.core.scroll,this.set_state(c,d),!1;if(c.core.selected)return h=this,this.deselect_all(),a.each(c.core.selected,function(a,b){h.select_node(b,!1,!0)}),delete c.core.selected,this.set_state(c,d),!1;for(i in c)c.hasOwnProperty(i)&&"core"!==i&&-1===a.inArray(i,this.settings.plugins)&&delete c[i];if(a.isEmptyObject(c.core))return delete c.core,this.set_state(c,d),!1}return a.isEmptyObject(c)?(c=null,d&&d.call(this),this.trigger("set_state"),!1):!0}return!1},refresh:function(b,c){this._data.core.state=c===!0?{}:this.get_state(),c&&a.isFunction(c)&&(this._data.core.state=c.call(this,this._data.core.state)),this._cnt=0,this._model.data={},this._model.data[a.jstree.root]={id:a.jstree.root,parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}},this._data.core.selected=[],this._data.core.last_clicked=null,this._data.core.focused=null;var d=this.get_container_ul()[0].className;b||(this.element.html("<ul class='"+d+"' role='group'><li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>"+this.get_string("Loading ...")+"</a></li></ul>"),this.element.attr("aria-activedescendant","j"+this._id+"_loading")),this.load_node(a.jstree.root,function(b,c){c&&(this.get_container_ul()[0].className=d,this._firstChild(this.get_container_ul()[0])&&this.element.attr("aria-activedescendant",this._firstChild(this.get_container_ul()[0]).id),this.set_state(a.extend(!0,{},this._data.core.state),function(){this.trigger("refresh")})),this._data.core.state=null})},refresh_node:function(b){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var c=[],d=[],e=this._data.core.selected.concat([]);d.push(b.id),b.state.opened===!0&&c.push(b.id),this.get_node(b,!0).find(".jstree-open").each(function(){d.push(this.id),c.push(this.id)}),this._load_nodes(d,a.proxy(function(a){this.open_node(c,!1,0),this.select_node(e),this.trigger("refresh_node",{node:b,nodes:a})},this),!1,!0)},set_id:function(b,c){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var d,e,f=this._model.data,g=b.id;for(c=c.toString(),f[b.parent].children[a.inArray(b.id,f[b.parent].children)]=c,d=0,e=b.parents.length;e>d;d++)f[b.parents[d]].children_d[a.inArray(b.id,f[b.parents[d]].children_d)]=c;for(d=0,e=b.children.length;e>d;d++)f[b.children[d]].parent=c;for(d=0,e=b.children_d.length;e>d;d++)f[b.children_d[d]].parents[a.inArray(b.id,f[b.children_d[d]].parents)]=c;return d=a.inArray(b.id,this._data.core.selected),-1!==d&&(this._data.core.selected[d]=c),d=this.get_node(b.id,!0),d&&(d.attr("id",c),this.element.attr("aria-activedescendant")===b.id&&this.element.attr("aria-activedescendant",c)),delete f[b.id],b.id=c,b.li_attr.id=c,f[c]=b,this.trigger("set_id",{node:b,"new":b.id,old:g}),!0},get_text:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.text:!1},set_text:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.set_text(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.text=c,this.get_node(b,!0).length&&this.redraw_node(b.id),this.trigger("set_text",{obj:b,text:c}),!0):!1},get_json:function(b,c,d){if(b=this.get_node(b||a.jstree.root),!b)return!1;c&&c.flat&&!d&&(d=[]);var e={id:b.id,text:b.text,icon:this.get_icon(b),li_attr:a.extend(!0,{},b.li_attr),a_attr:a.extend(!0,{},b.a_attr),state:{},data:c&&c.no_data?!1:a.extend(!0,{},b.data)},f,g;if(c&&c.flat?e.parent=b.parent:e.children=[],c&&c.no_state)delete e.state;else for(f in b.state)b.state.hasOwnProperty(f)&&(e.state[f]=b.state[f]);if(c&&c.no_li_attr&&delete e.li_attr,c&&c.no_a_attr&&delete e.a_attr,c&&c.no_id&&(delete e.id,e.li_attr&&e.li_attr.id&&delete e.li_attr.id,e.a_attr&&e.a_attr.id&&delete e.a_attr.id),c&&c.flat&&b.id!==a.jstree.root&&d.push(e),!c||!c.no_children)for(f=0,g=b.children.length;g>f;f++)c&&c.flat?this.get_json(b.children[f],c,d):e.children.push(this.get_json(b.children[f],c));return c&&c.flat?d:b.id===a.jstree.root?e.children:e},create_node:function(c,d,e,f,g){if(null===c&&(c=a.jstree.root),c=this.get_node(c),!c)return!1;if(e=e===b?"last":e,!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(c))return this.load_node(c,function(){this.create_node(c,d,e,f,!0)});d||(d={text:this.get_string("New node")}),"string"==typeof d&&(d={text:d}),d.text===b&&(d.text=this.get_string("New node"));var h,i,j,k;switch(c.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":h=this.get_node(c.parent),e=a.inArray(c.id,h.children),c=h;break;case"after":h=this.get_node(c.parent),e=a.inArray(c.id,h.children)+1,c=h;break;case"inside":case"first":e=0;break;case"last":e=c.children.length;break;default:e||(e=0)}if(e>c.children.length&&(e=c.children.length),d.id||(d.id=!0),!this.check("create_node",d,c,e))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(d.id===!0&&delete d.id,d=this._parse_model_from_json(d,c.id,c.parents.concat()),!d)return!1;for(h=this.get_node(d),i=[],i.push(d),i=i.concat(h.children_d),this.trigger("model",{nodes:i,parent:c.id}),c.children_d=c.children_d.concat(i),j=0,k=c.parents.length;k>j;j++)this._model.data[c.parents[j]].children_d=this._model.data[c.parents[j]].children_d.concat(i);for(d=h,h=[],j=0,k=c.children.length;k>j;j++)h[j>=e?j+1:j]=c.children[j];return h[e]=d.id,c.children=h,this.redraw_node(c,!0),f&&f.call(this,this.get_node(d)),this.trigger("create_node",{node:this.get_node(d),parent:c.id,position:e}),d.id},rename_node:function(b,c){var d,e,f;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.rename_node(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=b.text,this.check("rename_node",b,this.get_parent(b),c)?(this.set_text(b,c),this.trigger("rename_node",{node:b,text:c,old:f}),!0):(this.settings.core.error.call(this,this._data.core.last_error),!1)):!1},delete_node:function(b){var c,d,e,f,g,h,i,j,k,l,m,n;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.delete_node(b[c]);return!0}if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;if(e=this.get_node(b.parent),f=a.inArray(b.id,e.children),l=!1,!this.check("delete_node",b,e,f))return this.settings.core.error.call(this,this._data.core.last_error),!1;for(-1!==f&&(e.children=a.vakata.array_remove(e.children,f)),g=b.children_d.concat([]),g.push(b.id),h=0,i=b.parents.length;i>h;h++)this._model.data[b.parents[h]].children_d=a.vakata.array_filter(this._model.data[b.parents[h]].children_d,function(b){return-1===a.inArray(b,g)});for(j=0,k=g.length;k>j;j++)if(this._model.data[g[j]].state.selected){l=!0;break}for(l&&(this._data.core.selected=a.vakata.array_filter(this._data.core.selected,function(b){return-1===a.inArray(b,g)})),this.trigger("delete_node",{node:b,parent:e.id}),l&&this.trigger("changed",{action:"delete_node",node:b,selected:this._data.core.selected,parent:e.id}),j=0,k=g.length;k>j;j++)delete this._model.data[g[j]];return-1!==a.inArray(this._data.core.focused,g)&&(this._data.core.focused=null,m=this.element[0].scrollTop,n=this.element[0].scrollLeft,e.id===a.jstree.root?this._model.data[a.jstree.root].children[0]&&this.get_node(this._model.data[a.jstree.root].children[0],!0).children(".jstree-anchor").focus():this.get_node(e,!0).children(".jstree-anchor").focus(),this.element[0].scrollTop=m,this.element[0].scrollLeft=n),this.redraw_node(e,!0),!0},check:function(b,c,d,e,f){c=c&&c.id?c:this.get_node(c),d=d&&d.id?d:this.get_node(d);var g=b.match(/^move_node|copy_node|create_node$/i)?d:c,h=this.settings.core.check_callback;return"move_node"!==b&&"copy_node"!==b||f&&f.is_multi||c.id!==d.id&&("move_node"!==b||a.inArray(c.id,d.children)!==e)&&-1===a.inArray(d.id,c.children_d)?(g&&g.data&&(g=g.data),g&&g.functions&&(g.functions[b]===!1||g.functions[b]===!0)?(g.functions[b]===!1&&(this._data.core.last_error={error:"check",plugin:"core",id:"core_02",reason:"Node data prevents function: "+b,data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})}),g.functions[b]):h===!1||a.isFunction(h)&&h.call(this,b,c,d,e,f)===!1||h&&h[b]===!1?(this._data.core.last_error={error:"check",plugin:"core",id:"core_03",reason:"User config for core.check_callback prevents function: "+b,data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})},!1):!0):(this._data.core.last_error={error:"check",plugin:"core",id:"core_01",reason:"Moving parent inside child",data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})},!1)},last_error:function(){return this._data.core.last_error},move_node:function(c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w;if(d=this.get_node(d),e=e===b?0:e,!d)return!1;if(!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(d))return this.load_node(d,function(){this.move_node(c,d,e,f,!0,!1,i)});if(a.isArray(c)){if(1!==c.length){for(j=0,k=c.length;k>j;j++)(r=this.move_node(c[j],d,e,f,g,!1,i))&&(d=r,e="after");return this.redraw(),!0}c=c[0]}if(c=c&&c.id?c:this.get_node(c),!c||c.id===a.jstree.root)return!1;if(l=(c.parent||a.jstree.root).toString(),n=e.toString().match(/^(before|after)$/)&&d.id!==a.jstree.root?this.get_node(d.parent):d,o=i?i:this._model.data[c.id]?this:a.jstree.reference(c.id),p=!o||!o._id||this._id!==o._id,m=o&&o._id&&l&&o._model.data[l]&&o._model.data[l].children?a.inArray(c.id,o._model.data[l].children):-1,o&&o._id&&(c=o._model.data[c.id]),p)return(r=this.copy_node(c,d,e,f,g,!1,i))?(o&&o.delete_node(c),r):!1;switch(d.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":e=a.inArray(d.id,n.children);break;case"after":e=a.inArray(d.id,n.children)+1;break;case"inside":case"first":e=0;break;case"last":e=n.children.length;break;default:e||(e=0)}if(e>n.children.length&&(e=n.children.length),!this.check("move_node",c,n,e,{core:!0,origin:i,is_multi:o&&o._id&&o._id!==this._id,is_foreign:!o||!o._id}))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(c.parent===n.id){for(q=n.children.concat(),r=a.inArray(c.id,q),-1!==r&&(q=a.vakata.array_remove(q,r),e>r&&e--),r=[],s=0,t=q.length;t>s;s++)r[s>=e?s+1:s]=q[s];r[e]=c.id,n.children=r,this._node_changed(n.id),this.redraw(n.id===a.jstree.root)}else{for(r=c.children_d.concat(),r.push(c.id),s=0,t=c.parents.length;t>s;s++){for(q=[],w=o._model.data[c.parents[s]].children_d,u=0,v=w.length;v>u;u++)-1===a.inArray(w[u],r)&&q.push(w[u]);o._model.data[c.parents[s]].children_d=q}for(o._model.data[l].children=a.vakata.array_remove_item(o._model.data[l].children,c.id),s=0,t=n.parents.length;t>s;s++)this._model.data[n.parents[s]].children_d=this._model.data[n.parents[s]].children_d.concat(r);for(q=[],s=0,t=n.children.length;t>s;s++)q[s>=e?s+1:s]=n.children[s];for(q[e]=c.id,n.children=q,n.children_d.push(c.id),n.children_d=n.children_d.concat(c.children_d),c.parent=n.id,r=n.parents.concat(),r.unshift(n.id),w=c.parents.length,c.parents=r,r=r.concat(),s=0,t=c.children_d.length;t>s;s++)this._model.data[c.children_d[s]].parents=this._model.data[c.children_d[s]].parents.slice(0,-1*w),Array.prototype.push.apply(this._model.data[c.children_d[s]].parents,r);(l===a.jstree.root||n.id===a.jstree.root)&&(this._model.force_full_redraw=!0),this._model.force_full_redraw||(this._node_changed(l),this._node_changed(n.id)),h||this.redraw()}return f&&f.call(this,c,n,e),this.trigger("move_node",{node:c,parent:n.id,position:e,old_parent:l,old_position:m,is_multi:o&&o._id&&o._id!==this._id,is_foreign:!o||!o._id,old_instance:o,new_instance:this}),c.id},copy_node:function(c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t;if(d=this.get_node(d),e=e===b?0:e,!d)return!1;if(!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(d))return this.load_node(d,function(){this.copy_node(c,d,e,f,!0,!1,i)});if(a.isArray(c)){if(1!==c.length){for(j=0,k=c.length;k>j;j++)(m=this.copy_node(c[j],d,e,f,g,!0,i))&&(d=m,e="after");return this.redraw(),!0}c=c[0]}if(c=c&&c.id?c:this.get_node(c),!c||c.id===a.jstree.root)return!1;switch(q=(c.parent||a.jstree.root).toString(),r=e.toString().match(/^(before|after)$/)&&d.id!==a.jstree.root?this.get_node(d.parent):d,s=i?i:this._model.data[c.id]?this:a.jstree.reference(c.id),t=!s||!s._id||this._id!==s._id,s&&s._id&&(c=s._model.data[c.id]),d.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":e=a.inArray(d.id,r.children);break;case"after":e=a.inArray(d.id,r.children)+1;break;case"inside":case"first":e=0;break;case"last":e=r.children.length;break;default:e||(e=0)}if(e>r.children.length&&(e=r.children.length),!this.check("copy_node",c,r,e,{core:!0,origin:i,is_multi:s&&s._id&&s._id!==this._id,is_foreign:!s||!s._id}))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(p=s?s.get_json(c,{no_id:!0,no_data:!0,no_state:!0}):c,!p)return!1;if(p.id===!0&&delete p.id,p=this._parse_model_from_json(p,r.id,r.parents.concat()),!p)return!1;for(m=this.get_node(p),c&&c.state&&c.state.loaded===!1&&(m.state.loaded=!1),l=[],l.push(p),l=l.concat(m.children_d),this.trigger("model",{nodes:l,parent:r.id}),n=0,o=r.parents.length;o>n;n++)this._model.data[r.parents[n]].children_d=this._model.data[r.parents[n]].children_d.concat(l);for(l=[],n=0,o=r.children.length;o>n;n++)l[n>=e?n+1:n]=r.children[n];return l[e]=m.id,r.children=l,r.children_d.push(m.id),r.children_d=r.children_d.concat(m.children_d),r.id===a.jstree.root&&(this._model.force_full_redraw=!0),this._model.force_full_redraw||this._node_changed(r.id),h||this.redraw(r.id===a.jstree.root),f&&f.call(this,m,r,e),this.trigger("copy_node",{node:m,original:c,parent:r.id,position:e,old_parent:q,old_position:s&&s._id&&q&&s._model.data[q]&&s._model.data[q].children?a.inArray(c.id,s._model.data[q].children):-1,is_multi:s&&s._id&&s._id!==this._id,is_foreign:!s||!s._id,old_instance:s,new_instance:this}),m.id},cut:function(b){if(b||(b=this._data.core.selected.concat()),a.isArray(b)||(b=[b]),!b.length)return!1;var c=[],g,h,i;for(h=0,i=b.length;i>h;h++)g=this.get_node(b[h]),g&&g.id&&g.id!==a.jstree.root&&c.push(g);return c.length?(d=c,f=this,e="move_node",void this.trigger("cut",{node:b})):!1},copy:function(b){if(b||(b=this._data.core.selected.concat()),a.isArray(b)||(b=[b]),!b.length)return!1;var c=[],g,h,i;for(h=0,i=b.length;i>h;h++)g=this.get_node(b[h]),g&&g.id&&g.id!==a.jstree.root&&c.push(g);return c.length?(d=c,f=this,e="copy_node",void this.trigger("copy",{node:b})):!1},get_buffer:function(){return{mode:e,node:d,inst:f}},can_paste:function(){return e!==!1&&d!==!1},paste:function(a,b){return a=this.get_node(a),a&&e&&e.match(/^(copy_node|move_node)$/)&&d?(this[e](d,a,b,!1,!1,!1,f)&&this.trigger("paste",{parent:a.id,node:d,mode:e}),d=!1,e=!1,void(f=!1)):!1},clear_buffer:function(){d=!1,e=!1,f=!1,this.trigger("clear_buffer")},edit:function(b,c,d){var e,f,g,h,j,k,l,m,n,o=!1;return(b=this.get_node(b))?this.settings.core.check_callback===!1?(this._data.core.last_error={error:"check",plugin:"core",id:"core_07",reason:"Could not edit node because of check_callback"},this.settings.core.error.call(this,this._data.core.last_error),!1):(n=b,c="string"==typeof c?c:b.text,this.set_text(b,""),b=this._open_to(b),n.text=c,e=this._data.core.rtl,f=this.element.width(),this._data.core.focused=n.id,g=b.children(".jstree-anchor").focus(),h=a("<span>"),j=c,k=a("<div />",{css:{position:"absolute",top:"-200px",left:e?"0px":"-1000px",visibility:"hidden"}}).appendTo("body"),l=a("<input />",{value:j,"class":"jstree-rename-input",css:{padding:"0",border:"1px solid silver","box-sizing":"border-box",display:"inline-block",height:this._data.core.li_height+"px",lineHeight:this._data.core.li_height+"px",width:"150px"},blur:a.proxy(function(c){c.stopImmediatePropagation(),c.preventDefault();var e=h.children(".jstree-rename-input"),f=e.val(),i=this.settings.core.force_text,m;""===f&&(f=j),k.remove(),h.replaceWith(g),h.remove(),j=i?j:a("<div></div>").append(a.parseHTML(j)).html(),this.set_text(b,j),m=!!this.rename_node(b,i?a("<div></div>").text(f).text():a("<div></div>").append(a.parseHTML(f)).html()),m||this.set_text(b,j),this._data.core.focused=n.id,setTimeout(a.proxy(function(){var a=this.get_node(n.id,!0);a.length&&(this._data.core.focused=n.id,a.children(".jstree-anchor").focus())},this),0),d&&d.call(this,n,m,o),l=null},this),keydown:function(a){var b=a.which;27===b&&(o=!0,this.value=j),(27===b||13===b||37===b||38===b||39===b||40===b||32===b)&&a.stopImmediatePropagation(),(27===b||13===b)&&(a.preventDefault(),this.blur())},click:function(a){a.stopImmediatePropagation()},mousedown:function(a){a.stopImmediatePropagation()},keyup:function(a){l.width(Math.min(k.text("pW"+this.value).width(),f))},keypress:function(a){return 13===a.which?!1:void 0}}),m={fontFamily:g.css("fontFamily")||"",fontSize:g.css("fontSize")||"", +fontWeight:g.css("fontWeight")||"",fontStyle:g.css("fontStyle")||"",fontStretch:g.css("fontStretch")||"",fontVariant:g.css("fontVariant")||"",letterSpacing:g.css("letterSpacing")||"",wordSpacing:g.css("wordSpacing")||""},h.attr("class",g.attr("class")).append(g.contents().clone()).append(l),g.replaceWith(h),k.css(m),l.css(m).width(Math.min(k.text("pW"+l[0].value).width(),f))[0].select(),void a(i).one("mousedown.jstree touchstart.jstree dnd_start.vakata",function(b){l&&b.target!==l&&a(l).blur()})):!1},set_theme:function(b,c){if(!b)return!1;if(c===!0){var d=this.settings.core.themes.dir;d||(d=a.jstree.path+"/themes"),c=d+"/"+b+"/style.css"}c&&-1===a.inArray(c,g)&&(a("head").append('<link rel="stylesheet" href="'+c+'" type="text/css" />'),g.push(c)),this._data.core.themes.name&&this.element.removeClass("jstree-"+this._data.core.themes.name),this._data.core.themes.name=b,this.element.addClass("jstree-"+b),this.element[this.settings.core.themes.responsive?"addClass":"removeClass"]("jstree-"+b+"-responsive"),this.trigger("set_theme",{theme:b})},get_theme:function(){return this._data.core.themes.name},set_theme_variant:function(a){this._data.core.themes.variant&&this.element.removeClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant),this._data.core.themes.variant=a,a&&this.element.addClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant)},get_theme_variant:function(){return this._data.core.themes.variant},show_stripes:function(){this._data.core.themes.stripes=!0,this.get_container_ul().addClass("jstree-striped"),this.trigger("show_stripes")},hide_stripes:function(){this._data.core.themes.stripes=!1,this.get_container_ul().removeClass("jstree-striped"),this.trigger("hide_stripes")},toggle_stripes:function(){this._data.core.themes.stripes?this.hide_stripes():this.show_stripes()},show_dots:function(){this._data.core.themes.dots=!0,this.get_container_ul().removeClass("jstree-no-dots"),this.trigger("show_dots")},hide_dots:function(){this._data.core.themes.dots=!1,this.get_container_ul().addClass("jstree-no-dots"),this.trigger("hide_dots")},toggle_dots:function(){this._data.core.themes.dots?this.hide_dots():this.show_dots()},show_icons:function(){this._data.core.themes.icons=!0,this.get_container_ul().removeClass("jstree-no-icons"),this.trigger("show_icons")},hide_icons:function(){this._data.core.themes.icons=!1,this.get_container_ul().addClass("jstree-no-icons"),this.trigger("hide_icons")},toggle_icons:function(){this._data.core.themes.icons?this.hide_icons():this.show_icons()},show_ellipsis:function(){this._data.core.themes.ellipsis=!0,this.get_container_ul().addClass("jstree-ellipsis"),this.trigger("show_ellipsis")},hide_ellipsis:function(){this._data.core.themes.ellipsis=!1,this.get_container_ul().removeClass("jstree-ellipsis"),this.trigger("hide_ellipsis")},toggle_ellipsis:function(){this._data.core.themes.ellipsis?this.hide_ellipsis():this.show_ellipsis()},set_icon:function(c,d){var e,f,g,h;if(a.isArray(c)){for(c=c.slice(),e=0,f=c.length;f>e;e++)this.set_icon(c[e],d);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?(h=c.icon,c.icon=d===!0||null===d||d===b||""===d?!0:d,g=this.get_node(c,!0).children(".jstree-anchor").children(".jstree-themeicon"),d===!1?this.hide_icon(c):d===!0||null===d||d===b||""===d?(g.removeClass("jstree-themeicon-custom "+h).css("background","").removeAttr("rel"),h===!1&&this.show_icon(c)):-1===d.indexOf("/")&&-1===d.indexOf(".")?(g.removeClass(h).css("background",""),g.addClass(d+" jstree-themeicon-custom").attr("rel",d),h===!1&&this.show_icon(c)):(g.removeClass(h).css("background",""),g.addClass("jstree-themeicon-custom").css("background","url('"+d+"') center center no-repeat").attr("rel",d),h===!1&&this.show_icon(c)),!0):!1},get_icon:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.icon:!1},hide_icon:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.hide_icon(b[c]);return!0}return b=this.get_node(b),b&&b!==a.jstree.root?(b.icon=!1,this.get_node(b,!0).children(".jstree-anchor").children(".jstree-themeicon").addClass("jstree-themeicon-hidden"),!0):!1},show_icon:function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.show_icon(b[c]);return!0}return b=this.get_node(b),b&&b!==a.jstree.root?(e=this.get_node(b,!0),b.icon=e.length?e.children(".jstree-anchor").children(".jstree-themeicon").attr("rel"):!0,b.icon||(b.icon=!0),e.children(".jstree-anchor").children(".jstree-themeicon").removeClass("jstree-themeicon-hidden"),!0):!1}},a.vakata={},a.vakata.attributes=function(b,c){b=a(b)[0];var d=c?{}:[];return b&&b.attributes&&a.each(b.attributes,function(b,e){-1===a.inArray(e.name.toLowerCase(),["style","contenteditable","hasfocus","tabindex"])&&null!==e.value&&""!==a.trim(e.value)&&(c?d[e.name]=e.value:d.push(e.name))}),d},a.vakata.array_unique=function(a){var c=[],d,e,f,g={};for(d=0,f=a.length;f>d;d++)g[a[d]]===b&&(c.push(a[d]),g[a[d]]=!0);return c},a.vakata.array_remove=function(a,b){return a.splice(b,1),a},a.vakata.array_remove_item=function(b,c){var d=a.inArray(c,b);return-1!==d?a.vakata.array_remove(b,d):b},a.vakata.array_filter=function(a,b,c,d,e){if(a.filter)return a.filter(b,c);d=[];for(e in a)~~e+""==e+""&&e>=0&&b.call(c,a[e],+e,a)&&d.push(a[e]);return d},a.jstree.plugins.changed=function(a,b){var c=[];this.trigger=function(a,d){var e,f;if(d||(d={}),"changed"===a.replace(".jstree","")){d.changed={selected:[],deselected:[]};var g={};for(e=0,f=c.length;f>e;e++)g[c[e]]=1;for(e=0,f=d.selected.length;f>e;e++)g[d.selected[e]]?g[d.selected[e]]=2:d.changed.selected.push(d.selected[e]);for(e=0,f=c.length;f>e;e++)1===g[c[e]]&&d.changed.deselected.push(c[e]);c=d.selected.slice()}b.trigger.call(this,a,d)},this.refresh=function(a,d){return c=[],b.refresh.apply(this,arguments)}};var j=i.createElement("I");j.className="jstree-icon jstree-checkbox",j.setAttribute("role","presentation"),a.jstree.defaults.checkbox={visible:!0,three_state:!0,whole_node:!0,keep_selected_style:!0,cascade:"",tie_selection:!0},a.jstree.plugins.checkbox=function(c,d){this.bind=function(){d.bind.call(this),this._data.checkbox.uto=!1,this._data.checkbox.selected=[],this.settings.checkbox.three_state&&(this.settings.checkbox.cascade="up+down+undetermined"),this.element.on("init.jstree",a.proxy(function(){this._data.checkbox.visible=this.settings.checkbox.visible,this.settings.checkbox.keep_selected_style||this.element.addClass("jstree-checkbox-no-clicked"),this.settings.checkbox.tie_selection&&this.element.addClass("jstree-checkbox-selection")},this)).on("loading.jstree",a.proxy(function(){this[this._data.checkbox.visible?"show_checkboxes":"hide_checkboxes"]()},this)),-1!==this.settings.checkbox.cascade.indexOf("undetermined")&&this.element.on("changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree",a.proxy(function(){this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(a.proxy(this._undetermined,this),50)},this)),this.settings.checkbox.tie_selection||this.element.on("model.jstree",a.proxy(function(a,b){var c=this._model.data,d=c[b.parent],e=b.nodes,f,g;for(f=0,g=e.length;g>f;f++)c[e[f]].state.checked=c[e[f]].state.checked||c[e[f]].original&&c[e[f]].original.state&&c[e[f]].original.state.checked,c[e[f]].state.checked&&this._data.checkbox.selected.push(e[f])},this)),(-1!==this.settings.checkbox.cascade.indexOf("up")||-1!==this.settings.checkbox.cascade.indexOf("down"))&&this.element.on("model.jstree",a.proxy(function(b,c){var d=this._model.data,e=d[c.parent],f=c.nodes,g=[],h,i,j,k,l,m,n=this.settings.checkbox.cascade,o=this.settings.checkbox.tie_selection;if(-1!==n.indexOf("down"))if(e.state[o?"selected":"checked"]){for(i=0,j=f.length;j>i;i++)d[f[i]].state[o?"selected":"checked"]=!0;this._data[o?"core":"checkbox"].selected=this._data[o?"core":"checkbox"].selected.concat(f)}else for(i=0,j=f.length;j>i;i++)if(d[f[i]].state[o?"selected":"checked"]){for(k=0,l=d[f[i]].children_d.length;l>k;k++)d[d[f[i]].children_d[k]].state[o?"selected":"checked"]=!0;this._data[o?"core":"checkbox"].selected=this._data[o?"core":"checkbox"].selected.concat(d[f[i]].children_d)}if(-1!==n.indexOf("up")){for(i=0,j=e.children_d.length;j>i;i++)d[e.children_d[i]].children.length||g.push(d[e.children_d[i]].parent);for(g=a.vakata.array_unique(g),k=0,l=g.length;l>k;k++){e=d[g[k]];while(e&&e.id!==a.jstree.root){for(h=0,i=0,j=e.children.length;j>i;i++)h+=d[e.children[i]].state[o?"selected":"checked"];if(h!==j)break;e.state[o?"selected":"checked"]=!0,this._data[o?"core":"checkbox"].selected.push(e.id),m=this.get_node(e,!0),m&&m.length&&m.attr("aria-selected",!0).children(".jstree-anchor").addClass(o?"jstree-clicked":"jstree-checked"),e=this.get_node(e.parent)}}}this._data[o?"core":"checkbox"].selected=a.vakata.array_unique(this._data[o?"core":"checkbox"].selected)},this)).on(this.settings.checkbox.tie_selection?"select_node.jstree":"check_node.jstree",a.proxy(function(b,c){var d=c.node,e=this._model.data,f=this.get_node(d.parent),g=this.get_node(d,!0),h,i,j,k,l=this.settings.checkbox.cascade,m=this.settings.checkbox.tie_selection,n={},o=this._data[m?"core":"checkbox"].selected;for(h=0,i=o.length;i>h;h++)n[o[h]]=!0;if(-1!==l.indexOf("down"))for(h=0,i=d.children_d.length;i>h;h++)n[d.children_d[h]]=!0,k=e[d.children_d[h]],k.state[m?"selected":"checked"]=!0,k&&k.original&&k.original.state&&k.original.state.undetermined&&(k.original.state.undetermined=!1);if(-1!==l.indexOf("up"))while(f&&f.id!==a.jstree.root){for(j=0,h=0,i=f.children.length;i>h;h++)j+=e[f.children[h]].state[m?"selected":"checked"];if(j!==i)break;f.state[m?"selected":"checked"]=!0,n[f.id]=!0,k=this.get_node(f,!0),k&&k.length&&k.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"),f=this.get_node(f.parent)}o=[];for(h in n)n.hasOwnProperty(h)&&o.push(h);this._data[m?"core":"checkbox"].selected=o,-1!==l.indexOf("down")&&g.length&&g.find(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked").parent().attr("aria-selected",!0)},this)).on(this.settings.checkbox.tie_selection?"deselect_all.jstree":"uncheck_all.jstree",a.proxy(function(b,c){var d=this.get_node(a.jstree.root),e=this._model.data,f,g,h;for(f=0,g=d.children_d.length;g>f;f++)h=e[d.children_d[f]],h&&h.original&&h.original.state&&h.original.state.undetermined&&(h.original.state.undetermined=!1)},this)).on(this.settings.checkbox.tie_selection?"deselect_node.jstree":"uncheck_node.jstree",a.proxy(function(b,c){var d=c.node,e=this.get_node(d,!0),f,g,h,i=this.settings.checkbox.cascade,j=this.settings.checkbox.tie_selection,k=this._data[j?"core":"checkbox"].selected,l={};if(d&&d.original&&d.original.state&&d.original.state.undetermined&&(d.original.state.undetermined=!1),-1!==i.indexOf("down"))for(f=0,g=d.children_d.length;g>f;f++)h=this._model.data[d.children_d[f]],h.state[j?"selected":"checked"]=!1,h&&h.original&&h.original.state&&h.original.state.undetermined&&(h.original.state.undetermined=!1);if(-1!==i.indexOf("up"))for(f=0,g=d.parents.length;g>f;f++)h=this._model.data[d.parents[f]],h.state[j?"selected":"checked"]=!1,h&&h.original&&h.original.state&&h.original.state.undetermined&&(h.original.state.undetermined=!1),h=this.get_node(d.parents[f],!0),h&&h.length&&h.attr("aria-selected",!1).children(".jstree-anchor").removeClass(j?"jstree-clicked":"jstree-checked");for(l={},f=0,g=k.length;g>f;f++)-1!==i.indexOf("down")&&-1!==a.inArray(k[f],d.children_d)||-1!==i.indexOf("up")&&-1!==a.inArray(k[f],d.parents)||(l[k[f]]=!0);k=[];for(f in l)l.hasOwnProperty(f)&&k.push(f);this._data[j?"core":"checkbox"].selected=k,-1!==i.indexOf("down")&&e.length&&e.find(".jstree-anchor").removeClass(j?"jstree-clicked":"jstree-checked").parent().attr("aria-selected",!1)},this)),-1!==this.settings.checkbox.cascade.indexOf("up")&&this.element.on("delete_node.jstree",a.proxy(function(b,c){var d=this.get_node(c.parent),e=this._model.data,f,g,h,i,j=this.settings.checkbox.tie_selection;while(d&&d.id!==a.jstree.root&&!d.state[j?"selected":"checked"]){for(h=0,f=0,g=d.children.length;g>f;f++)h+=e[d.children[f]].state[j?"selected":"checked"];if(!(g>0&&h===g))break;d.state[j?"selected":"checked"]=!0,this._data[j?"core":"checkbox"].selected.push(d.id),i=this.get_node(d,!0),i&&i.length&&i.attr("aria-selected",!0).children(".jstree-anchor").addClass(j?"jstree-clicked":"jstree-checked"),d=this.get_node(d.parent)}},this)).on("move_node.jstree",a.proxy(function(b,c){var d=c.is_multi,e=c.old_parent,f=this.get_node(c.parent),g=this._model.data,h,i,j,k,l,m=this.settings.checkbox.tie_selection;if(!d){h=this.get_node(e);while(h&&h.id!==a.jstree.root&&!h.state[m?"selected":"checked"]){for(i=0,j=0,k=h.children.length;k>j;j++)i+=g[h.children[j]].state[m?"selected":"checked"];if(!(k>0&&i===k))break;h.state[m?"selected":"checked"]=!0,this._data[m?"core":"checkbox"].selected.push(h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"),h=this.get_node(h.parent)}}h=f;while(h&&h.id!==a.jstree.root){for(i=0,j=0,k=h.children.length;k>j;j++)i+=g[h.children[j]].state[m?"selected":"checked"];if(i===k)h.state[m?"selected":"checked"]||(h.state[m?"selected":"checked"]=!0,this._data[m?"core":"checkbox"].selected.push(h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"));else{if(!h.state[m?"selected":"checked"])break;h.state[m?"selected":"checked"]=!1,this._data[m?"core":"checkbox"].selected=a.vakata.array_remove_item(this._data[m?"core":"checkbox"].selected,h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!1).children(".jstree-anchor").removeClass(m?"jstree-clicked":"jstree-checked")}h=this.get_node(h.parent)}},this))},this._undetermined=function(){if(null!==this.element){var c,d,e,f,g={},h=this._model.data,i=this.settings.checkbox.tie_selection,j=this._data[i?"core":"checkbox"].selected,k=[],l=this;for(c=0,d=j.length;d>c;c++)if(h[j[c]]&&h[j[c]].parents)for(e=0,f=h[j[c]].parents.length;f>e;e++){if(g[h[j[c]].parents[e]]!==b)break;h[j[c]].parents[e]!==a.jstree.root&&(g[h[j[c]].parents[e]]=!0,k.push(h[j[c]].parents[e]))}for(this.element.find(".jstree-closed").not(":has(.jstree-children)").each(function(){var i=l.get_node(this),j;if(i.state.loaded){for(c=0,d=i.children_d.length;d>c;c++)if(j=h[i.children_d[c]],!j.state.loaded&&j.original&&j.original.state&&j.original.state.undetermined&&j.original.state.undetermined===!0)for(g[j.id]===b&&j.id!==a.jstree.root&&(g[j.id]=!0,k.push(j.id)),e=0,f=j.parents.length;f>e;e++)g[j.parents[e]]===b&&j.parents[e]!==a.jstree.root&&(g[j.parents[e]]=!0,k.push(j.parents[e]))}else if(i.original&&i.original.state&&i.original.state.undetermined&&i.original.state.undetermined===!0)for(g[i.id]===b&&i.id!==a.jstree.root&&(g[i.id]=!0,k.push(i.id)),e=0,f=i.parents.length;f>e;e++)g[i.parents[e]]===b&&i.parents[e]!==a.jstree.root&&(g[i.parents[e]]=!0,k.push(i.parents[e]))}),this.element.find(".jstree-undetermined").removeClass("jstree-undetermined"),c=0,d=k.length;d>c;c++)h[k[c]].state[i?"selected":"checked"]||(j=this.get_node(k[c],!0),j&&j.length&&j.children(".jstree-anchor").children(".jstree-checkbox").addClass("jstree-undetermined"))}},this.redraw_node=function(b,c,e,f){if(b=d.redraw_node.apply(this,arguments)){var g,h,i=null,k=null;for(g=0,h=b.childNodes.length;h>g;g++)if(b.childNodes[g]&&b.childNodes[g].className&&-1!==b.childNodes[g].className.indexOf("jstree-anchor")){i=b.childNodes[g];break}i&&(!this.settings.checkbox.tie_selection&&this._model.data[b.id].state.checked&&(i.className+=" jstree-checked"),k=j.cloneNode(!1),this._model.data[b.id].state.checkbox_disabled&&(k.className+=" jstree-checkbox-disabled"),i.insertBefore(k,i.childNodes[0]))}return e||-1===this.settings.checkbox.cascade.indexOf("undetermined")||(this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(a.proxy(this._undetermined,this),50)),b},this.show_checkboxes=function(){this._data.core.themes.checkboxes=!0,this.get_container_ul().removeClass("jstree-no-checkboxes")},this.hide_checkboxes=function(){this._data.core.themes.checkboxes=!1,this.get_container_ul().addClass("jstree-no-checkboxes")},this.toggle_checkboxes=function(){this._data.core.themes.checkboxes?this.hide_checkboxes():this.show_checkboxes()},this.is_undetermined=function(b){b=this.get_node(b);var c=this.settings.checkbox.cascade,d,e,f=this.settings.checkbox.tie_selection,g=this._data[f?"core":"checkbox"].selected,h=this._model.data;if(!b||b.state[f?"selected":"checked"]===!0||-1===c.indexOf("undetermined")||-1===c.indexOf("down")&&-1===c.indexOf("up"))return!1;if(!b.state.loaded&&b.original.state.undetermined===!0)return!0;for(d=0,e=b.children_d.length;e>d;d++)if(-1!==a.inArray(b.children_d[d],g)||!h[b.children_d[d]].state.loaded&&h[b.children_d[d]].original.state.undetermined)return!0;return!1},this.disable_checkbox=function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.disable_checkbox(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(e=this.get_node(b,!0),void(b.state.checkbox_disabled||(b.state.checkbox_disabled=!0,e&&e.length&&e.children(".jstree-anchor").children(".jstree-checkbox").addClass("jstree-checkbox-disabled"),this.trigger("disable_checkbox",{node:b})))):!1},this.enable_checkbox=function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.enable_checkbox(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(e=this.get_node(b,!0),void(b.state.checkbox_disabled&&(b.state.checkbox_disabled=!1,e&&e.length&&e.children(".jstree-anchor").children(".jstree-checkbox").removeClass("jstree-checkbox-disabled"),this.trigger("enable_checkbox",{node:b})))):!1},this.activate_node=function(b,c){return a(c.target).hasClass("jstree-checkbox-disabled")?!1:(this.settings.checkbox.tie_selection&&(this.settings.checkbox.whole_node||a(c.target).hasClass("jstree-checkbox"))&&(c.ctrlKey=!0),this.settings.checkbox.tie_selection||!this.settings.checkbox.whole_node&&!a(c.target).hasClass("jstree-checkbox")?d.activate_node.call(this,b,c):this.is_disabled(b)?!1:(this.is_checked(b)?this.uncheck_node(b,c):this.check_node(b,c),void this.trigger("activate_node",{node:this.get_node(b)})))},this.check_node=function(b,c){if(this.settings.checkbox.tie_selection)return this.select_node(b,!1,!0,c);var d,e,f,g;if(a.isArray(b)){for(b=b.slice(),e=0,f=b.length;f>e;e++)this.check_node(b[e],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(d=this.get_node(b,!0),void(b.state.checked||(b.state.checked=!0,this._data.checkbox.selected.push(b.id),d&&d.length&&d.children(".jstree-anchor").addClass("jstree-checked"),this.trigger("check_node",{node:b,selected:this._data.checkbox.selected,event:c})))):!1},this.uncheck_node=function(b,c){if(this.settings.checkbox.tie_selection)return this.deselect_node(b,!1,c);var d,e,f;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.uncheck_node(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=this.get_node(b,!0),void(b.state.checked&&(b.state.checked=!1,this._data.checkbox.selected=a.vakata.array_remove_item(this._data.checkbox.selected,b.id),f.length&&f.children(".jstree-anchor").removeClass("jstree-checked"),this.trigger("uncheck_node",{node:b,selected:this._data.checkbox.selected,event:c})))):!1},this.check_all=function(){if(this.settings.checkbox.tie_selection)return this.select_all();var b=this._data.checkbox.selected.concat([]),c,d;for(this._data.checkbox.selected=this._model.data[a.jstree.root].children_d.concat(),c=0,d=this._data.checkbox.selected.length;d>c;c++)this._model.data[this._data.checkbox.selected[c]]&&(this._model.data[this._data.checkbox.selected[c]].state.checked=!0);this.redraw(!0),this.trigger("check_all",{selected:this._data.checkbox.selected})},this.uncheck_all=function(){if(this.settings.checkbox.tie_selection)return this.deselect_all();var a=this._data.checkbox.selected.concat([]),b,c;for(b=0,c=this._data.checkbox.selected.length;c>b;b++)this._model.data[this._data.checkbox.selected[b]]&&(this._model.data[this._data.checkbox.selected[b]].state.checked=!1);this._data.checkbox.selected=[],this.element.find(".jstree-checked").removeClass("jstree-checked"),this.trigger("uncheck_all",{selected:this._data.checkbox.selected,node:a})},this.is_checked=function(b){return this.settings.checkbox.tie_selection?this.is_selected(b):(b=this.get_node(b),b&&b.id!==a.jstree.root?b.state.checked:!1)},this.get_checked=function(b){return this.settings.checkbox.tie_selection?this.get_selected(b):b?a.map(this._data.checkbox.selected,a.proxy(function(a){return this.get_node(a)},this)):this._data.checkbox.selected},this.get_top_checked=function(b){if(this.settings.checkbox.tie_selection)return this.get_top_selected(b);var c=this.get_checked(!0),d={},e,f,g,h;for(e=0,f=c.length;f>e;e++)d[c[e].id]=c[e];for(e=0,f=c.length;f>e;e++)for(g=0,h=c[e].children_d.length;h>g;g++)d[c[e].children_d[g]]&&delete d[c[e].children_d[g]];c=[];for(e in d)d.hasOwnProperty(e)&&c.push(e);return b?a.map(c,a.proxy(function(a){return this.get_node(a)},this)):c},this.get_bottom_checked=function(b){if(this.settings.checkbox.tie_selection)return this.get_bottom_selected(b);var c=this.get_checked(!0),d=[],e,f;for(e=0,f=c.length;f>e;e++)c[e].children.length||d.push(c[e].id);return b?a.map(d,a.proxy(function(a){return this.get_node(a)},this)):d},this.load_node=function(b,c){var e,f,g,h,i,j;if(!a.isArray(b)&&!this.settings.checkbox.tie_selection&&(j=this.get_node(b),j&&j.state.loaded))for(e=0,f=j.children_d.length;f>e;e++)this._model.data[j.children_d[e]].state.checked&&(i=!0,this._data.checkbox.selected=a.vakata.array_remove_item(this._data.checkbox.selected,j.children_d[e]));return d.load_node.apply(this,arguments)},this.get_state=function(){var a=d.get_state.apply(this,arguments);return this.settings.checkbox.tie_selection?a:(a.checkbox=this._data.checkbox.selected.slice(),a)},this.set_state=function(b,c){var e=d.set_state.apply(this,arguments);if(e&&b.checkbox){if(!this.settings.checkbox.tie_selection){this.uncheck_all();var f=this;a.each(b.checkbox,function(a,b){f.check_node(b)})}return delete b.checkbox,this.set_state(b,c),!1}return e},this.refresh=function(a,b){return this.settings.checkbox.tie_selection||(this._data.checkbox.selected=[]),d.refresh.apply(this,arguments)}},a.jstree.defaults.conditionalselect=function(){return!0},a.jstree.plugins.conditionalselect=function(a,b){this.activate_node=function(a,c){this.settings.conditionalselect.call(this,this.get_node(a),c)&&b.activate_node.call(this,a,c)}},a.jstree.defaults.contextmenu={select_node:!0,show_at_node:!0,items:function(b,c){return{create:{separator_before:!1,separator_after:!0,_disabled:!1,label:"Create",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.create_node(d,{},"last",function(a){setTimeout(function(){c.edit(a)},0)})}},rename:{separator_before:!1,separator_after:!1,_disabled:!1,label:"Rename",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.edit(d)}},remove:{separator_before:!1,icon:!1,separator_after:!1,_disabled:!1,label:"Delete",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.delete_node(c.get_selected()):c.delete_node(d)}},ccp:{separator_before:!0,icon:!1,separator_after:!1,label:"Edit",action:!1,submenu:{cut:{separator_before:!1,separator_after:!1,label:"Cut",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.cut(c.get_top_selected()):c.cut(d)}},copy:{separator_before:!1,icon:!1,separator_after:!1,label:"Copy",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.copy(c.get_top_selected()):c.copy(d)}},paste:{separator_before:!1,icon:!1,_disabled:function(b){return!a.jstree.reference(b.reference).can_paste()},separator_after:!1,label:"Paste",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.paste(d)}}}}}}},a.jstree.plugins.contextmenu=function(c,d){this.bind=function(){d.bind.call(this);var b=0,c=null,e,f;this.element.on("contextmenu.jstree",".jstree-anchor",a.proxy(function(a,d){"input"!==a.target.tagName.toLowerCase()&&(a.preventDefault(),b=a.ctrlKey?+new Date:0,(d||c)&&(b=+new Date+1e4),c&&clearTimeout(c),this.is_loading(a.currentTarget)||this.show_contextmenu(a.currentTarget,a.pageX,a.pageY,a))},this)).on("click.jstree",".jstree-anchor",a.proxy(function(c){this._data.contextmenu.visible&&(!b||+new Date-b>250)&&a.vakata.context.hide(),b=0},this)).on("touchstart.jstree",".jstree-anchor",function(b){b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(e=b.originalEvent.changedTouches[0].clientX,f=b.originalEvent.changedTouches[0].clientY,c=setTimeout(function(){a(b.currentTarget).trigger("contextmenu",!0)},750))}).on("touchmove.vakata.jstree",function(a){c&&a.originalEvent&&a.originalEvent.changedTouches&&a.originalEvent.changedTouches[0]&&(Math.abs(e-a.originalEvent.changedTouches[0].clientX)>50||Math.abs(f-a.originalEvent.changedTouches[0].clientY)>50)&&clearTimeout(c)}).on("touchend.vakata.jstree",function(a){c&&clearTimeout(c)}),a(i).on("context_hide.vakata.jstree",a.proxy(function(b,c){this._data.contextmenu.visible=!1,a(c.reference).removeClass("jstree-context")},this))},this.teardown=function(){this._data.contextmenu.visible&&a.vakata.context.hide(),d.teardown.call(this)},this.show_contextmenu=function(c,d,e,f){if(c=this.get_node(c),!c||c.id===a.jstree.root)return!1;var g=this.settings.contextmenu,h=this.get_node(c,!0),i=h.children(".jstree-anchor"),j=!1,k=!1;(g.show_at_node||d===b||e===b)&&(j=i.offset(),d=j.left,e=j.top+this._data.core.li_height),this.settings.contextmenu.select_node&&!this.is_selected(c)&&this.activate_node(c,f),k=g.items,a.isFunction(k)&&(k=k.call(this,c,a.proxy(function(a){this._show_contextmenu(c,d,e,a)},this))),a.isPlainObject(k)&&this._show_contextmenu(c,d,e,k)},this._show_contextmenu=function(b,c,d,e){var f=this.get_node(b,!0),g=f.children(".jstree-anchor");a(i).one("context_show.vakata.jstree",a.proxy(function(b,c){var d="jstree-contextmenu jstree-"+this.get_theme()+"-contextmenu";a(c.element).addClass(d),g.addClass("jstree-context")},this)),this._data.contextmenu.visible=!0,a.vakata.context.show(g,{x:c,y:d},e),this.trigger("show_contextmenu",{node:b,x:c,y:d})}},function(a){var b=!1,c={element:!1,reference:!1,position_x:0,position_y:0,items:[],html:"",is_visible:!1};a.vakata.context={settings:{hide_onmouseleave:0,icons:!0},_trigger:function(b){a(i).triggerHandler("context_"+b+".vakata",{reference:c.reference,element:c.element,position:{x:c.position_x,y:c.position_y}})},_execute:function(b){return b=c.items[b],b&&(!b._disabled||a.isFunction(b._disabled)&&!b._disabled({item:b,reference:c.reference,element:c.element}))&&b.action?b.action.call(null,{item:b,reference:c.reference,element:c.element,position:{x:c.position_x,y:c.position_y}}):!1},_parse:function(b,d){if(!b)return!1;d||(c.html="",c.items=[]);var e="",f=!1,g;return d&&(e+="<ul>"),a.each(b,function(b,d){return d?(c.items.push(d),!f&&d.separator_before&&(e+="<li class='vakata-context-separator'><a href='#' "+(a.vakata.context.settings.icons?"":'style="margin-left:0px;"')+"> </a></li>"),f=!1,e+="<li class='"+(d._class||"")+(d._disabled===!0||a.isFunction(d._disabled)&&d._disabled({item:d,reference:c.reference,element:c.element})?" vakata-contextmenu-disabled ":"")+"' "+(d.shortcut?" data-shortcut='"+d.shortcut+"' ":"")+">",e+="<a href='#' rel='"+(c.items.length-1)+"' "+(d.title?"title='"+d.title+"'":"")+">",a.vakata.context.settings.icons&&(e+="<i ",d.icon&&(e+=-1!==d.icon.indexOf("/")||-1!==d.icon.indexOf(".")?" style='background:url(\""+d.icon+"\") center center no-repeat' ":" class='"+d.icon+"' "),e+="></i><span class='vakata-contextmenu-sep'> </span>"),e+=(a.isFunction(d.label)?d.label({item:b,reference:c.reference,element:c.element}):d.label)+(d.shortcut?' <span class="vakata-contextmenu-shortcut vakata-contextmenu-shortcut-'+d.shortcut+'">'+(d.shortcut_label||"")+"</span>":"")+"</a>",d.submenu&&(g=a.vakata.context._parse(d.submenu,!0),g&&(e+=g)),e+="</li>",void(d.separator_after&&(e+="<li class='vakata-context-separator'><a href='#' "+(a.vakata.context.settings.icons?"":'style="margin-left:0px;"')+"> </a></li>",f=!0))):!0}),e=e.replace(/<li class\='vakata-context-separator'\><\/li\>$/,""),d&&(e+="</ul>"),d||(c.html=e,a.vakata.context._trigger("parse")),e.length>10?e:!1},_show_submenu:function(c){if(c=a(c),c.length&&c.children("ul").length){var d=c.children("ul"),e=c.offset().left,f=e+c.outerWidth(),g=c.offset().top,h=d.width(),i=d.height(),j=a(window).width()+a(window).scrollLeft(),k=a(window).height()+a(window).scrollTop();b?c[f-(h+10+c.outerWidth())<0?"addClass":"removeClass"]("vakata-context-left"):c[f+h>j&&e>j-f?"addClass":"removeClass"]("vakata-context-right"),g+i+10>k&&d.css("bottom","-1px"),c.hasClass("vakata-context-right")?h>e&&d.css("margin-right",e-h):h>j-f&&d.css("margin-left",j-f-h),d.show()}},show:function(d,e,f){var g,h,i,j,k,l,m,n,o=!0;switch(c.element&&c.element.length&&c.element.width(""),o){case!e&&!d:return!1;case!!e&&!!d:c.reference=d,c.position_x=e.x,c.position_y=e.y;break;case!e&&!!d:c.reference=d,g=d.offset(),c.position_x=g.left+d.outerHeight(),c.position_y=g.top;break;case!!e&&!d:c.position_x=e.x,c.position_y=e.y}d&&!f&&a(d).data("vakata_contextmenu")&&(f=a(d).data("vakata_contextmenu")),a.vakata.context._parse(f)&&c.element.html(c.html),c.items.length&&(c.element.appendTo("body"),h=c.element,i=c.position_x,j=c.position_y,k=h.width(),l=h.height(),m=a(window).width()+a(window).scrollLeft(),n=a(window).height()+a(window).scrollTop(),b&&(i-=h.outerWidth()-a(d).outerWidth(),i<a(window).scrollLeft()+20&&(i=a(window).scrollLeft()+20)),i+k+20>m&&(i=m-(k+20)),j+l+20>n&&(j=n-(l+20)),c.element.css({left:i,top:j}).show().find("a").first().focus().parent().addClass("vakata-context-hover"),c.is_visible=!0,a.vakata.context._trigger("show"))},hide:function(){c.is_visible&&(c.element.hide().find("ul").hide().end().find(":focus").blur().end().detach(),c.is_visible=!1,a.vakata.context._trigger("hide"))}},a(function(){b="rtl"===a("body").css("direction");var d=!1;c.element=a("<ul class='vakata-context'></ul>"),c.element.on("mouseenter","li",function(b){b.stopImmediatePropagation(),a.contains(this,b.relatedTarget)||(d&&clearTimeout(d),c.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(),a(this).siblings().find("ul").hide().end().end().parentsUntil(".vakata-context","li").addBack().addClass("vakata-context-hover"),a.vakata.context._show_submenu(this))}).on("mouseleave","li",function(b){a.contains(this,b.relatedTarget)||a(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover")}).on("mouseleave",function(b){a(this).find(".vakata-context-hover").removeClass("vakata-context-hover"),a.vakata.context.settings.hide_onmouseleave&&(d=setTimeout(function(b){return function(){a.vakata.context.hide()}}(this),a.vakata.context.settings.hide_onmouseleave))}).on("click","a",function(b){b.preventDefault(),a(this).blur().parent().hasClass("vakata-context-disabled")||a.vakata.context._execute(a(this).attr("rel"))===!1||a.vakata.context.hide()}).on("keydown","a",function(b){var d=null;switch(b.which){case 13:case 32:b.type="click",b.preventDefault(),a(b.currentTarget).trigger(b);break;case 37:c.is_visible&&(c.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 38:c.is_visible&&(d=c.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(), +d.length||(d=c.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last()),d.addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 39:c.is_visible&&(c.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 40:c.is_visible&&(d=c.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(),d.length||(d=c.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first()),d.addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 27:a.vakata.context.hide(),b.preventDefault()}}).on("keydown",function(a){a.preventDefault();var b=c.element.find(".vakata-contextmenu-shortcut-"+a.which).parent();b.parent().not(".vakata-context-disabled")&&b.click()}),a(i).on("mousedown.vakata.jstree",function(b){c.is_visible&&!a.contains(c.element[0],b.target)&&a.vakata.context.hide()}).on("context_show.vakata.jstree",function(a,d){c.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"),b&&c.element.addClass("vakata-context-rtl").css("direction","rtl"),c.element.find("ul").hide().end()})})}(a),a.jstree.defaults.dnd={copy:!0,open_timeout:500,is_draggable:!0,check_while_dragging:!0,always_copy:!1,inside_pos:0,drag_selection:!0,touch:!0,large_drop_target:!1,large_drag_target:!1,use_html5:!1};var k,l;a.jstree.plugins.dnd=function(b,c){this.init=function(a,b){c.init.call(this,a,b),this.settings.dnd.use_html5=this.settings.dnd.use_html5&&"draggable"in i.createElement("span")},this.bind=function(){c.bind.call(this),this.element.on(this.settings.dnd.use_html5?"dragstart.jstree":"mousedown.jstree touchstart.jstree",this.settings.dnd.large_drag_target?".jstree-node":".jstree-anchor",a.proxy(function(b){if(this.settings.dnd.large_drag_target&&a(b.target).closest(".jstree-node")[0]!==b.currentTarget)return!0;if("touchstart"===b.type&&(!this.settings.dnd.touch||"selected"===this.settings.dnd.touch&&!a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").hasClass("jstree-clicked")))return!0;var c=this.get_node(b.target),d=this.is_selected(c)&&this.settings.dnd.drag_selection?this.get_top_selected().length:1,e=d>1?d+" "+this.get_string("nodes"):this.get_text(b.currentTarget);if(this.settings.core.force_text&&(e=a.vakata.html.escape(e)),c&&c.id&&c.id!==a.jstree.root&&(1===b.which||"touchstart"===b.type||"dragstart"===b.type)&&(this.settings.dnd.is_draggable===!0||a.isFunction(this.settings.dnd.is_draggable)&&this.settings.dnd.is_draggable.call(this,d>1?this.get_top_selected(!0):[c],b))){if(k={jstree:!0,origin:this,obj:this.get_node(c,!0),nodes:d>1?this.get_top_selected():[c.id]},l=b.currentTarget,!this.settings.dnd.use_html5)return this.element.trigger("mousedown.jstree"),a.vakata.dnd.start(b,k,'<div id="jstree-dnd" class="jstree-'+this.get_theme()+" jstree-"+this.get_theme()+"-"+this.get_theme_variant()+" "+(this.settings.core.themes.responsive?" jstree-dnd-responsive":"")+'"><i class="jstree-icon jstree-er"></i>'+e+'<ins class="jstree-copy" style="display:none;">+</ins></div>');a.vakata.dnd._trigger("start",b,{helper:a(),element:l,data:k})}},this)),this.settings.dnd.use_html5&&this.element.on("dragover.jstree",function(b){return b.preventDefault(),a.vakata.dnd._trigger("move",b,{helper:a(),element:l,data:k}),!1}).on("drop.jstree",a.proxy(function(b){return b.preventDefault(),a.vakata.dnd._trigger("stop",b,{helper:a(),element:l,data:k}),!1},this))},this.redraw_node=function(a,b,d,e){if(a=c.redraw_node.apply(this,arguments),a&&this.settings.dnd.use_html5)if(this.settings.dnd.large_drag_target)a.setAttribute("draggable",!0);else{var f,g,h=null;for(f=0,g=a.childNodes.length;g>f;f++)if(a.childNodes[f]&&a.childNodes[f].className&&-1!==a.childNodes[f].className.indexOf("jstree-anchor")){h=a.childNodes[f];break}h&&h.setAttribute("draggable",!0)}return a}},a(function(){var c=!1,d=!1,e=!1,f=!1,g=a('<div id="jstree-marker"> </div>').hide();a(i).on("dnd_start.vakata.jstree",function(a,b){c=!1,e=!1,b&&b.data&&b.data.jstree&&g.appendTo("body")}).on("dnd_move.vakata.jstree",function(h,i){if(f&&(i.event&&"dragover"===i.event.type&&i.event.target===e.target||clearTimeout(f)),i&&i.data&&i.data.jstree&&(!i.event.target.id||"jstree-marker"!==i.event.target.id)){e=i.event;var j=a.jstree.reference(i.event.target),k=!1,l=!1,m=!1,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D;if(j&&j._data&&j._data.dnd)if(g.attr("class","jstree-"+j.get_theme()+(j.settings.core.themes.responsive?" jstree-dnd-responsive":"")),C=i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey)),i.helper.children().attr("class","jstree-"+j.get_theme()+" jstree-"+j.get_theme()+"-"+j.get_theme_variant()+" "+(j.settings.core.themes.responsive?" jstree-dnd-responsive":"")).find(".jstree-copy").first()[C?"show":"hide"](),i.event.target!==j.element[0]&&i.event.target!==j.get_container_ul()[0]||0!==j.get_container_ul().children().length){if(k=j.settings.dnd.large_drop_target?a(i.event.target).closest(".jstree-node").children(".jstree-anchor"):a(i.event.target).closest(".jstree-anchor"),k&&k.length&&k.parent().is(".jstree-closed, .jstree-open, .jstree-leaf")&&(l=k.offset(),m=(i.event.pageY!==b?i.event.pageY:i.event.originalEvent.pageY)-l.top,q=k.outerHeight(),t=q/3>m?["b","i","a"]:m>q-q/3?["a","i","b"]:m>q/2?["i","a","b"]:["i","b","a"],a.each(t,function(b,e){switch(e){case"b":o=l.left-6,p=l.top,r=j.get_parent(k),s=k.parent().index();break;case"i":A=j.settings.dnd.inside_pos,B=j.get_node(k.parent()),o=l.left-2,p=l.top+q/2+1,r=B.id,s="first"===A?0:"last"===A?B.children.length:Math.min(A,B.children.length);break;case"a":o=l.left-6,p=l.top+q,r=j.get_parent(k),s=k.parent().index()+1}for(u=!0,v=0,w=i.data.nodes.length;w>v;v++)if(x=i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey))?"copy_node":"move_node",y=s,"move_node"===x&&"a"===e&&i.data.origin&&i.data.origin===j&&r===j.get_parent(i.data.nodes[v])&&(z=j.get_node(r),y>a.inArray(i.data.nodes[v],z.children)&&(y-=1)),u=u&&(j&&j.settings&&j.settings.dnd&&j.settings.dnd.check_while_dragging===!1||j.check(x,i.data.origin&&i.data.origin!==j?i.data.origin.get_node(i.data.nodes[v]):i.data.nodes[v],r,y,{dnd:!0,ref:j.get_node(k.parent()),pos:e,origin:i.data.origin,is_multi:i.data.origin&&i.data.origin!==j,is_foreign:!i.data.origin})),!u){j&&j.last_error&&(d=j.last_error());break}return"i"===e&&k.parent().is(".jstree-closed")&&j.settings.dnd.open_timeout&&(f=setTimeout(function(a,b){return function(){a.open_node(b)}}(j,k),j.settings.dnd.open_timeout)),u?(D=j.get_node(r,!0),D.hasClass(".jstree-dnd-parent")||(a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),D.addClass("jstree-dnd-parent")),c={ins:j,par:r,pos:"i"!==e||"last"!==A||0!==s||j.is_loaded(B)?s:"last"},g.css({left:o+"px",top:p+"px"}).show(),i.helper.find(".jstree-icon").first().removeClass("jstree-er").addClass("jstree-ok"),i.event.originalEvent&&i.event.originalEvent.dataTransfer&&(i.event.originalEvent.dataTransfer.dropEffect=C?"copy":"move"),d={},t=!0,!1):void 0}),t===!0))return}else{for(u=!0,v=0,w=i.data.nodes.length;w>v;v++)if(u=u&&j.check(i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey))?"copy_node":"move_node",i.data.origin&&i.data.origin!==j?i.data.origin.get_node(i.data.nodes[v]):i.data.nodes[v],a.jstree.root,"last",{dnd:!0,ref:j.get_node(a.jstree.root),pos:"i",origin:i.data.origin,is_multi:i.data.origin&&i.data.origin!==j,is_foreign:!i.data.origin}),!u)break;if(u)return c={ins:j,par:a.jstree.root,pos:"last"},g.hide(),i.helper.find(".jstree-icon").first().removeClass("jstree-er").addClass("jstree-ok"),void(i.event.originalEvent&&i.event.originalEvent.dataTransfer&&(i.event.originalEvent.dataTransfer.dropEffect=C?"copy":"move"))}a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),c=!1,i.helper.find(".jstree-icon").removeClass("jstree-ok").addClass("jstree-er"),i.event.originalEvent&&i.event.originalEvent.dataTransfer&&(i.event.originalEvent.dataTransfer.dropEffect="none"),g.hide()}}).on("dnd_scroll.vakata.jstree",function(a,b){b&&b.data&&b.data.jstree&&(g.hide(),c=!1,e=!1,b.helper.find(".jstree-icon").first().removeClass("jstree-ok").addClass("jstree-er"))}).on("dnd_stop.vakata.jstree",function(b,h){if(a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),f&&clearTimeout(f),h&&h.data&&h.data.jstree){g.hide().detach();var i,j,k=[];if(c){for(i=0,j=h.data.nodes.length;j>i;i++)k[i]=h.data.origin?h.data.origin.get_node(h.data.nodes[i]):h.data.nodes[i];c.ins[h.data.origin&&(h.data.origin.settings.dnd.always_copy||h.data.origin.settings.dnd.copy&&(h.event.metaKey||h.event.ctrlKey))?"copy_node":"move_node"](k,c.par,c.pos,!1,!1,!1,h.data.origin)}else i=a(h.event.target).closest(".jstree"),i.length&&d&&d.error&&"check"===d.error&&(i=i.jstree(!0),i&&i.settings.core.error.call(this,d));e=!1,c=!1}}).on("keyup.jstree keydown.jstree",function(b,h){h=a.vakata.dnd._get(),h&&h.data&&h.data.jstree&&("keyup"===b.type&&27===b.which?(f&&clearTimeout(f),c=!1,d=!1,e=!1,f=!1,g.hide().detach(),a.vakata.dnd._clean()):(h.helper.find(".jstree-copy").first()[h.data.origin&&(h.data.origin.settings.dnd.always_copy||h.data.origin.settings.dnd.copy&&(b.metaKey||b.ctrlKey))?"show":"hide"](),e&&(e.metaKey=b.metaKey,e.ctrlKey=b.ctrlKey,a.vakata.dnd._trigger("move",e))))})}),function(a){a.vakata.html={div:a("<div />"),escape:function(b){return a.vakata.html.div.text(b).html()},strip:function(b){return a.vakata.html.div.empty().append(a.parseHTML(b)).text()}};var c={element:!1,target:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1,is_touch:!1};a.vakata.dnd={settings:{scroll_speed:10,scroll_proximity:20,helper_left:5,helper_top:10,threshold:5,threshold_touch:50},_trigger:function(c,d,e){e===b&&(e=a.vakata.dnd._get()),e.event=d,a(i).triggerHandler("dnd_"+c+".vakata",e)},_get:function(){return{data:c.data,element:c.element,helper:c.helper}},_clean:function(){c.helper&&c.helper.remove(),c.scroll_i&&(clearInterval(c.scroll_i),c.scroll_i=!1),c={element:!1,target:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1,is_touch:!1},a(i).off("mousemove.vakata.jstree touchmove.vakata.jstree",a.vakata.dnd.drag),a(i).off("mouseup.vakata.jstree touchend.vakata.jstree",a.vakata.dnd.stop)},_scroll:function(b){if(!c.scroll_e||!c.scroll_l&&!c.scroll_t)return c.scroll_i&&(clearInterval(c.scroll_i),c.scroll_i=!1),!1;if(!c.scroll_i)return c.scroll_i=setInterval(a.vakata.dnd._scroll,100),!1;if(b===!0)return!1;var d=c.scroll_e.scrollTop(),e=c.scroll_e.scrollLeft();c.scroll_e.scrollTop(d+c.scroll_t*a.vakata.dnd.settings.scroll_speed),c.scroll_e.scrollLeft(e+c.scroll_l*a.vakata.dnd.settings.scroll_speed),(d!==c.scroll_e.scrollTop()||e!==c.scroll_e.scrollLeft())&&a.vakata.dnd._trigger("scroll",c.scroll_e)},start:function(b,d,e){"touchstart"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_drag&&a.vakata.dnd.stop({});try{b.currentTarget.unselectable="on",b.currentTarget.onselectstart=function(){return!1},b.currentTarget.style&&(b.currentTarget.style.touchAction="none",b.currentTarget.style.msTouchAction="none",b.currentTarget.style.MozUserSelect="none")}catch(f){}return c.init_x=b.pageX,c.init_y=b.pageY,c.data=d,c.is_down=!0,c.element=b.currentTarget,c.target=b.target,c.is_touch="touchstart"===b.type,e!==!1&&(c.helper=a("<div id='vakata-dnd'></div>").html(e).css({display:"block",margin:"0",padding:"0",position:"absolute",top:"-2000px",lineHeight:"16px",zIndex:"10000"})),a(i).on("mousemove.vakata.jstree touchmove.vakata.jstree",a.vakata.dnd.drag),a(i).on("mouseup.vakata.jstree touchend.vakata.jstree",a.vakata.dnd.stop),!1},drag:function(b){if("touchmove"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_down){if(!c.is_drag){if(!(Math.abs(b.pageX-c.init_x)>(c.is_touch?a.vakata.dnd.settings.threshold_touch:a.vakata.dnd.settings.threshold)||Math.abs(b.pageY-c.init_y)>(c.is_touch?a.vakata.dnd.settings.threshold_touch:a.vakata.dnd.settings.threshold)))return;c.helper&&(c.helper.appendTo("body"),c.helper_w=c.helper.outerWidth()),c.is_drag=!0,a(c.target).one("click.vakata",!1),a.vakata.dnd._trigger("start",b)}var d=!1,e=!1,f=!1,g=!1,h=!1,j=!1,k=!1,l=!1,m=!1,n=!1;return c.scroll_t=0,c.scroll_l=0,c.scroll_e=!1,a(a(b.target).parentsUntil("body").addBack().get().reverse()).filter(function(){return/^auto|scroll$/.test(a(this).css("overflow"))&&(this.scrollHeight>this.offsetHeight||this.scrollWidth>this.offsetWidth)}).each(function(){var d=a(this),e=d.offset();return this.scrollHeight>this.offsetHeight&&(e.top+d.height()-b.pageY<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_t=1),b.pageY-e.top<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_t=-1)),this.scrollWidth>this.offsetWidth&&(e.left+d.width()-b.pageX<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_l=1),b.pageX-e.left<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_l=-1)),c.scroll_t||c.scroll_l?(c.scroll_e=a(this),!1):void 0}),c.scroll_e||(d=a(i),e=a(window),f=d.height(),g=e.height(),h=d.width(),j=e.width(),k=d.scrollTop(),l=d.scrollLeft(),f>g&&b.pageY-k<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_t=-1),f>g&&g-(b.pageY-k)<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_t=1),h>j&&b.pageX-l<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_l=-1),h>j&&j-(b.pageX-l)<a.vakata.dnd.settings.scroll_proximity&&(c.scroll_l=1),(c.scroll_t||c.scroll_l)&&(c.scroll_e=d)),c.scroll_e&&a.vakata.dnd._scroll(!0),c.helper&&(m=parseInt(b.pageY+a.vakata.dnd.settings.helper_top,10),n=parseInt(b.pageX+a.vakata.dnd.settings.helper_left,10),f&&m+25>f&&(m=f-50),h&&n+c.helper_w>h&&(n=h-(c.helper_w+2)),c.helper.css({left:n+"px",top:m+"px"})),a.vakata.dnd._trigger("move",b),!1}},stop:function(b){if("touchend"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_drag)b.target!==c.target&&a(c.target).off("click.vakata"),a.vakata.dnd._trigger("stop",b);else if("touchend"===b.type&&b.target===c.target){var d=setTimeout(function(){a(b.target).click()},100);a(b.target).one("click",function(){d&&clearTimeout(d)})}return a.vakata.dnd._clean(),!1}}}(a),a.jstree.defaults.massload=null,a.jstree.plugins.massload=function(b,c){this.init=function(a,b){this._data.massload={},c.init.call(this,a,b)},this._load_nodes=function(b,d,e,f){var g=this.settings.massload,h=JSON.stringify(b),i=[],j=this._model.data,k,l,m;if(!e){for(k=0,l=b.length;l>k;k++)(!j[b[k]]||!j[b[k]].state.loaded&&!j[b[k]].state.failed||f)&&(i.push(b[k]),m=this.get_node(b[k],!0),m&&m.length&&m.addClass("jstree-loading").attr("aria-busy",!0));if(this._data.massload={},i.length){if(a.isFunction(g))return g.call(this,i,a.proxy(function(a){var g,h;if(a)for(g in a)a.hasOwnProperty(g)&&(this._data.massload[g]=a[g]);for(g=0,h=b.length;h>g;g++)m=this.get_node(b[g],!0),m&&m.length&&m.removeClass("jstree-loading").attr("aria-busy",!1);c._load_nodes.call(this,b,d,e,f)},this));if("object"==typeof g&&g&&g.url)return g=a.extend(!0,{},g),a.isFunction(g.url)&&(g.url=g.url.call(this,i)),a.isFunction(g.data)&&(g.data=g.data.call(this,i)),a.ajax(g).done(a.proxy(function(a,g,h){var i,j;if(a)for(i in a)a.hasOwnProperty(i)&&(this._data.massload[i]=a[i]);for(i=0,j=b.length;j>i;i++)m=this.get_node(b[i],!0),m&&m.length&&m.removeClass("jstree-loading").attr("aria-busy",!1);c._load_nodes.call(this,b,d,e,f)},this)).fail(a.proxy(function(a){c._load_nodes.call(this,b,d,e,f)},this))}}return c._load_nodes.call(this,b,d,e,f)},this._load_node=function(b,d){var e=this._data.massload[b.id],f=null,g;return e?(f=this["string"==typeof e?"_append_html_data":"_append_json_data"](b,"string"==typeof e?a(a.parseHTML(e)).filter(function(){return 3!==this.nodeType}):e,function(a){d.call(this,a)}),g=this.get_node(b.id,!0),g&&g.length&&g.removeClass("jstree-loading").attr("aria-busy",!1),delete this._data.massload[b.id],f):c._load_node.call(this,b,d)}},a.jstree.defaults.search={ajax:!1,fuzzy:!1,case_sensitive:!1,show_only_matches:!1,show_only_matches_children:!1,close_opened_onclear:!0,search_leaves_only:!1,search_callback:!1},a.jstree.plugins.search=function(c,d){this.bind=function(){d.bind.call(this),this._data.search.str="",this._data.search.dom=a(),this._data.search.res=[],this._data.search.opn=[],this._data.search.som=!1,this._data.search.smc=!1,this._data.search.hdn=[],this.element.on("search.jstree",a.proxy(function(b,c){if(this._data.search.som&&c.res.length){var d=this._model.data,e,f,g=[],h,i;for(e=0,f=c.res.length;f>e;e++)if(d[c.res[e]]&&!d[c.res[e]].state.hidden&&(g.push(c.res[e]),g=g.concat(d[c.res[e]].parents),this._data.search.smc))for(h=0,i=d[c.res[e]].children_d.length;i>h;h++)d[d[c.res[e]].children_d[h]]&&!d[d[c.res[e]].children_d[h]].state.hidden&&g.push(d[c.res[e]].children_d[h]);g=a.vakata.array_remove_item(a.vakata.array_unique(g),a.jstree.root),this._data.search.hdn=this.hide_all(!0),this.show_node(g,!0),this.redraw(!0)}},this)).on("clear_search.jstree",a.proxy(function(a,b){this._data.search.som&&b.res.length&&(this.show_node(this._data.search.hdn,!0),this.redraw(!0))},this))},this.search=function(c,d,e,f,g,h){if(c===!1||""===a.trim(c.toString()))return this.clear_search();f=this.get_node(f),f=f&&f.id?f.id:null,c=c.toString();var i=this.settings.search,j=i.ajax?i.ajax:!1,k=this._model.data,l=null,m=[],n=[],o,p;if(this._data.search.res.length&&!g&&this.clear_search(),e===b&&(e=i.show_only_matches),h===b&&(h=i.show_only_matches_children),!d&&j!==!1)return a.isFunction(j)?j.call(this,c,a.proxy(function(b){b&&b.d&&(b=b.d),this._load_nodes(a.isArray(b)?a.vakata.array_unique(b):[],function(){this.search(c,!0,e,f,g,h)})},this),f):(j=a.extend({},j),j.data||(j.data={}),j.data.str=c,f&&(j.data.inside=f),this._data.search.lastRequest&&this._data.search.lastRequest.abort(),this._data.search.lastRequest=a.ajax(j).fail(a.proxy(function(){this._data.core.last_error={error:"ajax",plugin:"search",id:"search_01",reason:"Could not load search parents",data:JSON.stringify(j)},this.settings.core.error.call(this,this._data.core.last_error)},this)).done(a.proxy(function(b){b&&b.d&&(b=b.d),this._load_nodes(a.isArray(b)?a.vakata.array_unique(b):[],function(){this.search(c,!0,e,f,g,h)})},this)),this._data.search.lastRequest);if(g||(this._data.search.str=c,this._data.search.dom=a(),this._data.search.res=[],this._data.search.opn=[],this._data.search.som=e,this._data.search.smc=h),l=new a.vakata.search(c,!0,{caseSensitive:i.case_sensitive,fuzzy:i.fuzzy}),a.each(k[f?f:a.jstree.root].children_d,function(a,b){var d=k[b];d.text&&!d.state.hidden&&(!i.search_leaves_only||d.state.loaded&&0===d.children.length)&&(i.search_callback&&i.search_callback.call(this,c,d)||!i.search_callback&&l.search(d.text).isMatch)&&(m.push(b),n=n.concat(d.parents))}),m.length){for(n=a.vakata.array_unique(n),o=0,p=n.length;p>o;o++)n[o]!==a.jstree.root&&k[n[o]]&&this.open_node(n[o],null,0)===!0&&this._data.search.opn.push(n[o]);g?(this._data.search.dom=this._data.search.dom.add(a(this.element[0].querySelectorAll("#"+a.map(m,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #")))),this._data.search.res=a.vakata.array_unique(this._data.search.res.concat(m))):(this._data.search.dom=a(this.element[0].querySelectorAll("#"+a.map(m,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #"))),this._data.search.res=m),this._data.search.dom.children(".jstree-anchor").addClass("jstree-search")}this.trigger("search",{nodes:this._data.search.dom,str:c,res:this._data.search.res,show_only_matches:e})},this.clear_search=function(){this.settings.search.close_opened_onclear&&this.close_node(this._data.search.opn,0),this.trigger("clear_search",{nodes:this._data.search.dom,str:this._data.search.str,res:this._data.search.res}),this._data.search.res.length&&(this._data.search.dom=a(this.element[0].querySelectorAll("#"+a.map(this._data.search.res,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #"))),this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search")),this._data.search.str="",this._data.search.res=[],this._data.search.opn=[],this._data.search.dom=a()},this.redraw_node=function(b,c,e,f){if(b=d.redraw_node.apply(this,arguments),b&&-1!==a.inArray(b.id,this._data.search.res)){var g,h,i=null;for(g=0,h=b.childNodes.length;h>g;g++)if(b.childNodes[g]&&b.childNodes[g].className&&-1!==b.childNodes[g].className.indexOf("jstree-anchor")){i=b.childNodes[g];break}i&&(i.className+=" jstree-search")}return b}},function(a){a.vakata.search=function(b,c,d){d=d||{},d=a.extend({},a.vakata.search.defaults,d),d.fuzzy!==!1&&(d.fuzzy=!0),b=d.caseSensitive?b:b.toLowerCase();var e=d.location,f=d.distance,g=d.threshold,h=b.length,i,j,k,l;return h>32&&(d.fuzzy=!1),d.fuzzy&&(i=1<<h-1,j=function(){var a={},c=0;for(c=0;h>c;c++)a[b.charAt(c)]=0;for(c=0;h>c;c++)a[b.charAt(c)]|=1<<h-c-1;return a}(),k=function(a,b){var c=a/h,d=Math.abs(e-b);return f?c+d/f:d?1:c}),l=function(a){if(a=d.caseSensitive?a:a.toLowerCase(),b===a||-1!==a.indexOf(b))return{isMatch:!0,score:0};if(!d.fuzzy)return{isMatch:!1,score:1};var c,f,l=a.length,m=g,n=a.indexOf(b,e),o,p,q=h+l,r,s,t,u,v,w=1,x=[];for(-1!==n&&(m=Math.min(k(0,n),m),n=a.lastIndexOf(b,e+h),-1!==n&&(m=Math.min(k(0,n),m))),n=-1,c=0;h>c;c++){o=0,p=q;while(p>o)k(c,e+p)<=m?o=p:q=p,p=Math.floor((q-o)/2+o);for(q=p,s=Math.max(1,e-p+1),t=Math.min(e+p,l)+h,u=new Array(t+2),u[t+1]=(1<<c)-1,f=t;f>=s;f--)if(v=j[a.charAt(f-1)],0===c?u[f]=(u[f+1]<<1|1)&v:u[f]=(u[f+1]<<1|1)&v|((r[f+1]|r[f])<<1|1)|r[f+1],u[f]&i&&(w=k(c,f-1),m>=w)){if(m=w,n=f-1,x.push(n),!(n>e))break;s=Math.max(1,2*e-n)}if(k(c+1,e)>m)break;r=u}return{isMatch:n>=0,score:w}},c===!0?{search:l}:l(c)},a.vakata.search.defaults={location:0,distance:100,threshold:.6,fuzzy:!1,caseSensitive:!1}}(a),a.jstree.defaults.sort=function(a,b){return this.get_text(a)>this.get_text(b)?1:-1},a.jstree.plugins.sort=function(b,c){this.bind=function(){c.bind.call(this),this.element.on("model.jstree",a.proxy(function(a,b){this.sort(b.parent,!0)},this)).on("rename_node.jstree create_node.jstree",a.proxy(function(a,b){this.sort(b.parent||b.node.parent,!1),this.redraw_node(b.parent||b.node.parent,!0)},this)).on("move_node.jstree copy_node.jstree",a.proxy(function(a,b){this.sort(b.parent,!1),this.redraw_node(b.parent,!0)},this))},this.sort=function(b,c){var d,e;if(b=this.get_node(b),b&&b.children&&b.children.length&&(b.children.sort(a.proxy(this.settings.sort,this)),c))for(d=0,e=b.children_d.length;e>d;d++)this.sort(b.children_d[d],!1)}};var m=!1;a.jstree.defaults.state={key:"jstree",events:"changed.jstree open_node.jstree close_node.jstree check_node.jstree uncheck_node.jstree",ttl:!1,filter:!1},a.jstree.plugins.state=function(b,c){this.bind=function(){c.bind.call(this);var b=a.proxy(function(){this.element.on(this.settings.state.events,a.proxy(function(){m&&clearTimeout(m),m=setTimeout(a.proxy(function(){this.save_state()},this),100)},this)),this.trigger("state_ready")},this);this.element.on("ready.jstree",a.proxy(function(a,c){this.element.one("restore_state.jstree",b),this.restore_state()||b()},this))},this.save_state=function(){var b={state:this.get_state(),ttl:this.settings.state.ttl,sec:+new Date};a.vakata.storage.set(this.settings.state.key,JSON.stringify(b))},this.restore_state=function(){var b=a.vakata.storage.get(this.settings.state.key);if(b)try{b=JSON.parse(b)}catch(c){return!1}return b&&b.ttl&&b.sec&&+new Date-b.sec>b.ttl?!1:(b&&b.state&&(b=b.state),b&&a.isFunction(this.settings.state.filter)&&(b=this.settings.state.filter.call(this,b)),b?(this.element.one("set_state.jstree",function(c,d){d.instance.trigger("restore_state",{state:a.extend(!0,{},b)})}),this.set_state(b),!0):!1)},this.clear_state=function(){return a.vakata.storage.del(this.settings.state.key)}},function(a,b){a.vakata.storage={set:function(a,b){return window.localStorage.setItem(a,b)},get:function(a){return window.localStorage.getItem(a)},del:function(a){return window.localStorage.removeItem(a)}}}(a),a.jstree.defaults.types={"default":{}},a.jstree.defaults.types[a.jstree.root]={},a.jstree.plugins.types=function(c,d){this.init=function(c,e){var f,g;if(e&&e.types&&e.types["default"])for(f in e.types)if("default"!==f&&f!==a.jstree.root&&e.types.hasOwnProperty(f))for(g in e.types["default"])e.types["default"].hasOwnProperty(g)&&e.types[f][g]===b&&(e.types[f][g]=e.types["default"][g]);d.init.call(this,c,e),this._model.data[a.jstree.root].type=a.jstree.root},this.refresh=function(b,c){d.refresh.call(this,b,c),this._model.data[a.jstree.root].type=a.jstree.root},this.bind=function(){this.element.on("model.jstree",a.proxy(function(c,d){var e=this._model.data,f=d.nodes,g=this.settings.types,h,i,j="default",k;for(h=0,i=f.length;i>h;h++){if(j="default",e[f[h]].original&&e[f[h]].original.type&&g[e[f[h]].original.type]&&(j=e[f[h]].original.type),e[f[h]].data&&e[f[h]].data.jstree&&e[f[h]].data.jstree.type&&g[e[f[h]].data.jstree.type]&&(j=e[f[h]].data.jstree.type),e[f[h]].type=j,e[f[h]].icon===!0&&g[j].icon!==b&&(e[f[h]].icon=g[j].icon),g[j].li_attr!==b&&"object"==typeof g[j].li_attr)for(k in g[j].li_attr)if(g[j].li_attr.hasOwnProperty(k)){if("id"===k)continue;e[f[h]].li_attr[k]===b?e[f[h]].li_attr[k]=g[j].li_attr[k]:"class"===k&&(e[f[h]].li_attr["class"]=g[j].li_attr["class"]+" "+e[f[h]].li_attr["class"])}if(g[j].a_attr!==b&&"object"==typeof g[j].a_attr)for(k in g[j].a_attr)if(g[j].a_attr.hasOwnProperty(k)){if("id"===k)continue;e[f[h]].a_attr[k]===b?e[f[h]].a_attr[k]=g[j].a_attr[k]:"href"===k&&"#"===e[f[h]].a_attr[k]?e[f[h]].a_attr.href=g[j].a_attr.href:"class"===k&&(e[f[h]].a_attr["class"]=g[j].a_attr["class"]+" "+e[f[h]].a_attr["class"])}}e[a.jstree.root].type=a.jstree.root},this)),d.bind.call(this)},this.get_json=function(b,c,e){var f,g,h=this._model.data,i=c?a.extend(!0,{},c,{no_id:!1}):{},j=d.get_json.call(this,b,i,e);if(j===!1)return!1;if(a.isArray(j))for(f=0,g=j.length;g>f;f++)j[f].type=j[f].id&&h[j[f].id]&&h[j[f].id].type?h[j[f].id].type:"default",c&&c.no_id&&(delete j[f].id,j[f].li_attr&&j[f].li_attr.id&&delete j[f].li_attr.id,j[f].a_attr&&j[f].a_attr.id&&delete j[f].a_attr.id);else j.type=j.id&&h[j.id]&&h[j.id].type?h[j.id].type:"default",c&&c.no_id&&(j=this._delete_ids(j));return j},this._delete_ids=function(b){if(a.isArray(b)){for(var c=0,d=b.length;d>c;c++)b[c]=this._delete_ids(b[c]);return b}return delete b.id,b.li_attr&&b.li_attr.id&&delete b.li_attr.id,b.a_attr&&b.a_attr.id&&delete b.a_attr.id,b.children&&a.isArray(b.children)&&(b.children=this._delete_ids(b.children)),b},this.check=function(c,e,f,g,h){if(d.check.call(this,c,e,f,g,h)===!1)return!1;e=e&&e.id?e:this.get_node(e),f=f&&f.id?f:this.get_node(f);var i=e&&e.id?h&&h.origin?h.origin:a.jstree.reference(e.id):null,j,k,l,m;switch(i=i&&i._model&&i._model.data?i._model.data:null,c){case"create_node":case"move_node":case"copy_node":if("move_node"!==c||-1===a.inArray(e.id,f.children)){if(j=this.get_rules(f),j.max_children!==b&&-1!==j.max_children&&j.max_children===f.children.length)return this._data.core.last_error={error:"check",plugin:"types",id:"types_01",reason:"max_children prevents function: "+c,data:JSON.stringify({chk:c,pos:g,obj:e&&e.id?e.id:!1,par:f&&f.id?f.id:!1})},!1;if(j.valid_children!==b&&-1!==j.valid_children&&-1===a.inArray(e.type||"default",j.valid_children))return this._data.core.last_error={error:"check",plugin:"types",id:"types_02",reason:"valid_children prevents function: "+c,data:JSON.stringify({chk:c,pos:g,obj:e&&e.id?e.id:!1,par:f&&f.id?f.id:!1})},!1;if(i&&e.children_d&&e.parents){for(k=0,l=0,m=e.children_d.length;m>l;l++)k=Math.max(k,i[e.children_d[l]].parents.length);k=k-e.parents.length+1}(0>=k||k===b)&&(k=1);do{if(j.max_depth!==b&&-1!==j.max_depth&&j.max_depth<k)return this._data.core.last_error={error:"check",plugin:"types",id:"types_03",reason:"max_depth prevents function: "+c,data:JSON.stringify({chk:c,pos:g,obj:e&&e.id?e.id:!1,par:f&&f.id?f.id:!1})},!1;f=this.get_node(f.parent),j=this.get_rules(f),k++}while(f)}}return!0},this.get_rules=function(a){if(a=this.get_node(a),!a)return!1;var c=this.get_type(a,!0);return c.max_depth===b&&(c.max_depth=-1),c.max_children===b&&(c.max_children=-1),c.valid_children===b&&(c.valid_children=-1),c},this.get_type=function(b,c){return b=this.get_node(b),b?c?a.extend({type:b.type},this.settings.types[b.type]):b.type:!1},this.set_type=function(c,d){var e=this._model.data,f,g,h,i,j,k,l,m;if(a.isArray(c)){for(c=c.slice(),g=0,h=c.length;h>g;g++)this.set_type(c[g],d);return!0}if(f=this.settings.types,c=this.get_node(c),!f[d]||!c)return!1;if(l=this.get_node(c,!0),l&&l.length&&(m=l.children(".jstree-anchor")),i=c.type,j=this.get_icon(c),c.type=d,(j===!0||!f[i]||f[i].icon!==b&&j===f[i].icon)&&this.set_icon(c,f[d].icon!==b?f[d].icon:!0),f[i]&&f[i].li_attr!==b&&"object"==typeof f[i].li_attr)for(k in f[i].li_attr)if(f[i].li_attr.hasOwnProperty(k)){if("id"===k)continue;"class"===k?(e[c.id].li_attr["class"]=(e[c.id].li_attr["class"]||"").replace(f[i].li_attr[k],""),l&&l.removeClass(f[i].li_attr[k])):e[c.id].li_attr[k]===f[i].li_attr[k]&&(e[c.id].li_attr[k]=null,l&&l.removeAttr(k))}if(f[i]&&f[i].a_attr!==b&&"object"==typeof f[i].a_attr)for(k in f[i].a_attr)if(f[i].a_attr.hasOwnProperty(k)){if("id"===k)continue;"class"===k?(e[c.id].a_attr["class"]=(e[c.id].a_attr["class"]||"").replace(f[i].a_attr[k],""),m&&m.removeClass(f[i].a_attr[k])):e[c.id].a_attr[k]===f[i].a_attr[k]&&("href"===k?(e[c.id].a_attr[k]="#",m&&m.attr("href","#")):(delete e[c.id].a_attr[k],m&&m.removeAttr(k)))}if(f[d].li_attr!==b&&"object"==typeof f[d].li_attr)for(k in f[d].li_attr)if(f[d].li_attr.hasOwnProperty(k)){if("id"===k)continue;e[c.id].li_attr[k]===b?(e[c.id].li_attr[k]=f[d].li_attr[k],l&&("class"===k?l.addClass(f[d].li_attr[k]):l.attr(k,f[d].li_attr[k]))):"class"===k&&(e[c.id].li_attr["class"]=f[d].li_attr[k]+" "+e[c.id].li_attr["class"],l&&l.addClass(f[d].li_attr[k]))}if(f[d].a_attr!==b&&"object"==typeof f[d].a_attr)for(k in f[d].a_attr)if(f[d].a_attr.hasOwnProperty(k)){if("id"===k)continue;e[c.id].a_attr[k]===b?(e[c.id].a_attr[k]=f[d].a_attr[k],m&&("class"===k?m.addClass(f[d].a_attr[k]):m.attr(k,f[d].a_attr[k]))):"href"===k&&"#"===e[c.id].a_attr[k]?(e[c.id].a_attr.href=f[d].a_attr.href,m&&m.attr("href",f[d].a_attr.href)):"class"===k&&(e[c.id].a_attr["class"]=f[d].a_attr["class"]+" "+e[c.id].a_attr["class"],m&&m.addClass(f[d].a_attr[k]))}return!0}},a.jstree.defaults.unique={case_sensitive:!1,duplicate:function(a,b){return a+" ("+b+")"}},a.jstree.plugins.unique=function(c,d){this.check=function(b,c,e,f,g){if(d.check.call(this,b,c,e,f,g)===!1)return!1; +if(c=c&&c.id?c:this.get_node(c),e=e&&e.id?e:this.get_node(e),!e||!e.children)return!0;var h="rename_node"===b?f:c.text,i=[],j=this.settings.unique.case_sensitive,k=this._model.data,l,m;for(l=0,m=e.children.length;m>l;l++)i.push(j?k[e.children[l]].text:k[e.children[l]].text.toLowerCase());switch(j||(h=h.toLowerCase()),b){case"delete_node":return!0;case"rename_node":return l=-1===a.inArray(h,i)||c.text&&c.text[j?"toString":"toLowerCase"]()===h,l||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_01",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),l;case"create_node":return l=-1===a.inArray(h,i),l||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_04",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),l;case"copy_node":return l=-1===a.inArray(h,i),l||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_02",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),l;case"move_node":return l=c.parent===e.id&&(!g||!g.is_multi)||-1===a.inArray(h,i),l||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_03",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),l}return!0},this.create_node=function(c,e,f,g,h){if(!e||e.text===b){if(null===c&&(c=a.jstree.root),c=this.get_node(c),!c)return d.create_node.call(this,c,e,f,g,h);if(f=f===b?"last":f,!f.toString().match(/^(before|after)$/)&&!h&&!this.is_loaded(c))return d.create_node.call(this,c,e,f,g,h);e||(e={});var i,j,k,l,m,n=this._model.data,o=this.settings.unique.case_sensitive,p=this.settings.unique.duplicate;for(j=i=this.get_string("New node"),k=[],l=0,m=c.children.length;m>l;l++)k.push(o?n[c.children[l]].text:n[c.children[l]].text.toLowerCase());l=1;while(-1!==a.inArray(o?j:j.toLowerCase(),k))j=p.call(this,i,++l).toString();e.text=j}return d.create_node.call(this,c,e,f,g,h)}};var n=i.createElement("DIV");if(n.setAttribute("unselectable","on"),n.setAttribute("role","presentation"),n.className="jstree-wholerow",n.innerHTML=" ",a.jstree.plugins.wholerow=function(b,c){this.bind=function(){c.bind.call(this),this.element.on("ready.jstree set_state.jstree",a.proxy(function(){this.hide_dots()},this)).on("init.jstree loading.jstree ready.jstree",a.proxy(function(){this.get_container_ul().addClass("jstree-wholerow-ul")},this)).on("deselect_all.jstree",a.proxy(function(a,b){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked")},this)).on("changed.jstree",a.proxy(function(a,b){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked");var c=!1,d,e;for(d=0,e=b.selected.length;e>d;d++)c=this.get_node(b.selected[d],!0),c&&c.length&&c.children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("open_node.jstree",a.proxy(function(a,b){this.get_node(b.node,!0).find(".jstree-clicked").parent().children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("hover_node.jstree dehover_node.jstree",a.proxy(function(a,b){"hover_node"===a.type&&this.is_disabled(b.node)||this.get_node(b.node,!0).children(".jstree-wholerow")["hover_node"===a.type?"addClass":"removeClass"]("jstree-wholerow-hovered")},this)).on("contextmenu.jstree",".jstree-wholerow",a.proxy(function(b){if(this._data.contextmenu){b.preventDefault();var c=a.Event("contextmenu",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey,pageX:b.pageX,pageY:b.pageY});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c)}},this)).on("click.jstree",".jstree-wholerow",function(b){b.stopImmediatePropagation();var c=a.Event("click",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()}).on("dblclick.jstree",".jstree-wholerow",function(b){b.stopImmediatePropagation();var c=a.Event("dblclick",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()}).on("click.jstree",".jstree-leaf > .jstree-ocl",a.proxy(function(b){b.stopImmediatePropagation();var c=a.Event("click",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()},this)).on("mouseover.jstree",".jstree-wholerow, .jstree-icon",a.proxy(function(a){return a.stopImmediatePropagation(),this.is_disabled(a.currentTarget)||this.hover_node(a.currentTarget),!1},this)).on("mouseleave.jstree",".jstree-node",a.proxy(function(a){this.dehover_node(a.currentTarget)},this))},this.teardown=function(){this.settings.wholerow&&this.element.find(".jstree-wholerow").remove(),c.teardown.call(this)},this.redraw_node=function(b,d,e,f){if(b=c.redraw_node.apply(this,arguments)){var g=n.cloneNode(!0);-1!==a.inArray(b.id,this._data.core.selected)&&(g.className+=" jstree-wholerow-clicked"),this._data.core.focused&&this._data.core.focused===b.id&&(g.className+=" jstree-wholerow-hovered"),b.insertBefore(g,b.childNodes[0])}return b}},i.registerElement&&Object&&Object.create){var o=Object.create(HTMLElement.prototype);o.createdCallback=function(){var b={core:{},plugins:[]},c;for(c in a.jstree.plugins)a.jstree.plugins.hasOwnProperty(c)&&this.attributes[c]&&(b.plugins.push(c),this.getAttribute(c)&&JSON.parse(this.getAttribute(c))&&(b[c]=JSON.parse(this.getAttribute(c))));for(c in a.jstree.defaults.core)a.jstree.defaults.core.hasOwnProperty(c)&&this.attributes[c]&&(b.core[c]=JSON.parse(this.getAttribute(c))||this.getAttribute(c));a(this).jstree(b)};try{i.registerElement("vakata-jstree",{prototype:o})}catch(p){}}}}); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/dist/themes/default-dark/32px.png b/civicrm/bower_components/jstree/dist/themes/default-dark/32px.png new file mode 100644 index 0000000000000000000000000000000000000000..d6fd72114f8205ace7579894ec50cc37739b1471 Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default-dark/32px.png differ diff --git a/civicrm/bower_components/jstree/dist/themes/default-dark/40px.png b/civicrm/bower_components/jstree/dist/themes/default-dark/40px.png new file mode 100644 index 0000000000000000000000000000000000000000..4fc88e41e66508e4657b3ec6e5ec185a6084b7a9 Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default-dark/40px.png differ diff --git a/civicrm/bower_components/jstree/dist/themes/default-dark/style.css b/civicrm/bower_components/jstree/dist/themes/default-dark/style.css new file mode 100644 index 0000000000000000000000000000000000000000..3af003f2d558ba972b7612d6f5d0dd24e48339f0 --- /dev/null +++ b/civicrm/bower_components/jstree/dist/themes/default-dark/style.css @@ -0,0 +1,1146 @@ +/* jsTree default dark theme */ +.jstree-node, +.jstree-children, +.jstree-container-ul { + display: block; + margin: 0; + padding: 0; + list-style-type: none; + list-style-image: none; +} +.jstree-node { + white-space: nowrap; +} +.jstree-anchor { + display: inline-block; + color: black; + white-space: nowrap; + padding: 0 4px 0 1px; + margin: 0; + vertical-align: top; +} +.jstree-anchor:focus { + outline: 0; +} +.jstree-anchor, +.jstree-anchor:link, +.jstree-anchor:visited, +.jstree-anchor:hover, +.jstree-anchor:active { + text-decoration: none; + color: inherit; +} +.jstree-icon { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-icon:empty { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-ocl { + cursor: pointer; +} +.jstree-leaf > .jstree-ocl { + cursor: default; +} +.jstree .jstree-open > .jstree-children { + display: block; +} +.jstree .jstree-closed > .jstree-children, +.jstree .jstree-leaf > .jstree-children { + display: none; +} +.jstree-anchor > .jstree-themeicon { + margin-right: 2px; +} +.jstree-no-icons .jstree-themeicon, +.jstree-anchor > .jstree-themeicon-hidden { + display: none; +} +.jstree-hidden, +.jstree-node.jstree-hidden { + display: none; +} +.jstree-rtl .jstree-anchor { + padding: 0 1px 0 4px; +} +.jstree-rtl .jstree-anchor > .jstree-themeicon { + margin-left: 2px; + margin-right: 0; +} +.jstree-rtl .jstree-node { + margin-left: 0; +} +.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; +} +.jstree-wholerow-ul { + position: relative; + display: inline-block; + min-width: 100%; +} +.jstree-wholerow-ul .jstree-leaf > .jstree-ocl { + cursor: pointer; +} +.jstree-wholerow-ul .jstree-anchor, +.jstree-wholerow-ul .jstree-icon { + position: relative; +} +.jstree-wholerow-ul .jstree-wholerow { + width: 100%; + cursor: pointer; + position: absolute; + left: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.vakata-context { + display: none; +} +.vakata-context, +.vakata-context ul { + margin: 0; + padding: 2px; + position: absolute; + background: #f5f5f5; + border: 1px solid #979797; + box-shadow: 2px 2px 2px #999999; +} +.vakata-context ul { + list-style: none; + left: 100%; + margin-top: -2.7em; + margin-left: -4px; +} +.vakata-context .vakata-context-right ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context li { + list-style: none; +} +.vakata-context li > a { + display: block; + padding: 0 2em 0 2em; + text-decoration: none; + width: auto; + color: black; + white-space: nowrap; + line-height: 2.4em; + text-shadow: 1px 1px 0 white; + border-radius: 1px; +} +.vakata-context li > a:hover { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); + background-position: right center; + background-repeat: no-repeat; +} +.vakata-context li > a:focus { + outline: 0; +} +.vakata-context .vakata-context-hover > a { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context .vakata-context-separator > a, +.vakata-context .vakata-context-separator > a:hover { + background: white; + border: 0; + border-top: 1px solid #e2e3e3; + height: 1px; + min-height: 1px; + max-height: 1px; + padding: 0; + margin: 0 0 0 2.4em; + border-left: 1px solid #e0e0e0; + text-shadow: 0 0 0 transparent; + box-shadow: 0 0 0 transparent; + border-radius: 0; +} +.vakata-context .vakata-contextmenu-disabled a, +.vakata-context .vakata-contextmenu-disabled a:hover { + color: silver; + background-color: transparent; + border: 0; + box-shadow: 0 0 0; +} +.vakata-context li > a > i { + text-decoration: none; + display: inline-block; + width: 2.4em; + height: 2.4em; + background: transparent; + margin: 0 0 0 -2em; + vertical-align: top; + text-align: center; + line-height: 2.4em; +} +.vakata-context li > a > i:empty { + width: 2.4em; + line-height: 2.4em; +} +.vakata-context li > a .vakata-contextmenu-sep { + display: inline-block; + width: 1px; + height: 2.4em; + background: white; + margin: 0 0.5em 0 0; + border-left: 1px solid #e2e3e3; +} +.vakata-context .vakata-contextmenu-shortcut { + font-size: 0.8em; + color: silver; + opacity: 0.5; + display: none; +} +.vakata-context-rtl ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context-rtl li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); + background-position: left center; + background-repeat: no-repeat; +} +.vakata-context-rtl .vakata-context-separator > a { + margin: 0 2.4em 0 0; + border-left: 0; + border-right: 1px solid #e2e3e3; +} +.vakata-context-rtl .vakata-context-left ul { + right: auto; + left: 100%; + margin-left: -4px; + margin-right: auto; +} +.vakata-context-rtl li > a > i { + margin: 0 -2em 0 0; +} +.vakata-context-rtl li > a .vakata-contextmenu-sep { + margin: 0 0 0 0.5em; + border-left-color: white; + background: #e2e3e3; +} +#jstree-marker { + position: absolute; + top: 0; + left: 0; + margin: -5px 0 0 0; + padding: 0; + border-right: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid; + width: 0; + height: 0; + font-size: 0; + line-height: 0; +} +#jstree-dnd { + line-height: 16px; + margin: 0; + padding: 4px; +} +#jstree-dnd .jstree-icon, +#jstree-dnd .jstree-copy { + display: inline-block; + text-decoration: none; + margin: 0 2px 0 0; + padding: 0; + width: 16px; + height: 16px; +} +#jstree-dnd .jstree-ok { + background: green; +} +#jstree-dnd .jstree-er { + background: red; +} +#jstree-dnd .jstree-copy { + margin: 0 2px 0 2px; +} +.jstree-default-dark .jstree-node, +.jstree-default-dark .jstree-icon { + background-repeat: no-repeat; + background-color: transparent; +} +.jstree-default-dark .jstree-anchor, +.jstree-default-dark .jstree-animated, +.jstree-default-dark .jstree-wholerow { + transition: background-color 0.15s, box-shadow 0.15s; +} +.jstree-default-dark .jstree-hovered { + background: #555555; + border-radius: 2px; + box-shadow: inset 0 0 1px #555555; +} +.jstree-default-dark .jstree-context { + background: #555555; + border-radius: 2px; + box-shadow: inset 0 0 1px #555555; +} +.jstree-default-dark .jstree-clicked { + background: #5fa2db; + border-radius: 2px; + box-shadow: inset 0 0 1px #666666; +} +.jstree-default-dark .jstree-no-icons .jstree-anchor > .jstree-themeicon { + display: none; +} +.jstree-default-dark .jstree-disabled { + background: transparent; + color: #666666; +} +.jstree-default-dark .jstree-disabled.jstree-hovered { + background: transparent; + box-shadow: none; +} +.jstree-default-dark .jstree-disabled.jstree-clicked { + background: #333333; +} +.jstree-default-dark .jstree-disabled > .jstree-icon { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark .jstree-search { + font-style: italic; + color: #ffffff; + font-weight: bold; +} +.jstree-default-dark .jstree-no-checkboxes .jstree-checkbox { + display: none !important; +} +.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked { + background: transparent; + box-shadow: none; +} +.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered { + background: #555555; +} +.jstree-default-dark.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked { + background: transparent; +} +.jstree-default-dark.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered { + background: #555555; +} +.jstree-default-dark > .jstree-striped { + min-width: 100%; + display: inline-block; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; +} +.jstree-default-dark > .jstree-wholerow-ul .jstree-hovered, +.jstree-default-dark > .jstree-wholerow-ul .jstree-clicked { + background: transparent; + box-shadow: none; + border-radius: 0; +} +.jstree-default-dark .jstree-wholerow { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.jstree-default-dark .jstree-wholerow-hovered { + background: #555555; +} +.jstree-default-dark .jstree-wholerow-clicked { + background: #5fa2db; + background: -webkit-linear-gradient(top, #5fa2db 0%, #5fa2db 100%); + background: linear-gradient(to bottom, #5fa2db 0%, #5fa2db 100%); +} +.jstree-default-dark .jstree-node { + min-height: 24px; + line-height: 24px; + margin-left: 24px; + min-width: 24px; +} +.jstree-default-dark .jstree-anchor { + line-height: 24px; + height: 24px; +} +.jstree-default-dark .jstree-icon { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default-dark .jstree-icon:empty { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default-dark.jstree-rtl .jstree-node { + margin-right: 24px; +} +.jstree-default-dark .jstree-wholerow { + height: 24px; +} +.jstree-default-dark .jstree-node, +.jstree-default-dark .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark .jstree-node { + background-position: -292px -4px; + background-repeat: repeat-y; +} +.jstree-default-dark .jstree-last { + background: transparent; +} +.jstree-default-dark .jstree-open > .jstree-ocl { + background-position: -132px -4px; +} +.jstree-default-dark .jstree-closed > .jstree-ocl { + background-position: -100px -4px; +} +.jstree-default-dark .jstree-leaf > .jstree-ocl { + background-position: -68px -4px; +} +.jstree-default-dark .jstree-themeicon { + background-position: -260px -4px; +} +.jstree-default-dark > .jstree-no-dots .jstree-node, +.jstree-default-dark > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -4px; +} +.jstree-default-dark > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -4px; +} +.jstree-default-dark .jstree-disabled { + background: transparent; +} +.jstree-default-dark .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark .jstree-checkbox { + background-position: -164px -4px; +} +.jstree-default-dark .jstree-checkbox:hover { + background-position: -164px -36px; +} +.jstree-default-dark.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark .jstree-checked > .jstree-checkbox { + background-position: -228px -4px; +} +.jstree-default-dark.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark .jstree-checked > .jstree-checkbox:hover { + background-position: -228px -36px; +} +.jstree-default-dark .jstree-anchor > .jstree-undetermined { + background-position: -196px -4px; +} +.jstree-default-dark .jstree-anchor > .jstree-undetermined:hover { + background-position: -196px -36px; +} +.jstree-default-dark .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark > .jstree-striped { + background-size: auto 48px; +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -132px -36px; +} +.jstree-default-dark.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -100px -36px; +} +.jstree-default-dark.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -68px -36px; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -36px; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -36px; +} +.jstree-default-dark .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark .jstree-file { + background: url("32px.png") -100px -68px no-repeat; +} +.jstree-default-dark .jstree-folder { + background: url("32px.png") -260px -4px no-repeat; +} +.jstree-default-dark > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark { + line-height: 24px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark .jstree-ok, +#jstree-dnd.jstree-default-dark .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark i { + background: transparent; + width: 24px; + height: 24px; + line-height: 24px; +} +#jstree-dnd.jstree-default-dark .jstree-ok { + background-position: -4px -68px; +} +#jstree-dnd.jstree-default-dark .jstree-er { + background-position: -36px -68px; +} +.jstree-default-dark .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark .jstree-ellipsis .jstree-anchor { + width: calc(100% - 29px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small .jstree-node { + min-height: 18px; + line-height: 18px; + margin-left: 18px; + min-width: 18px; +} +.jstree-default-dark-small .jstree-anchor { + line-height: 18px; + height: 18px; +} +.jstree-default-dark-small .jstree-icon { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-dark-small .jstree-icon:empty { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + margin-right: 18px; +} +.jstree-default-dark-small .jstree-wholerow { + height: 18px; +} +.jstree-default-dark-small .jstree-node, +.jstree-default-dark-small .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark-small .jstree-node { + background-position: -295px -7px; + background-repeat: repeat-y; +} +.jstree-default-dark-small .jstree-last { + background: transparent; +} +.jstree-default-dark-small .jstree-open > .jstree-ocl { + background-position: -135px -7px; +} +.jstree-default-dark-small .jstree-closed > .jstree-ocl { + background-position: -103px -7px; +} +.jstree-default-dark-small .jstree-leaf > .jstree-ocl { + background-position: -71px -7px; +} +.jstree-default-dark-small .jstree-themeicon { + background-position: -263px -7px; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-node, +.jstree-default-dark-small > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -7px; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -7px; +} +.jstree-default-dark-small .jstree-disabled { + background: transparent; +} +.jstree-default-dark-small .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark-small .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark-small .jstree-checkbox { + background-position: -167px -7px; +} +.jstree-default-dark-small .jstree-checkbox:hover { + background-position: -167px -39px; +} +.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark-small .jstree-checked > .jstree-checkbox { + background-position: -231px -7px; +} +.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark-small .jstree-checked > .jstree-checkbox:hover { + background-position: -231px -39px; +} +.jstree-default-dark-small .jstree-anchor > .jstree-undetermined { + background-position: -199px -7px; +} +.jstree-default-dark-small .jstree-anchor > .jstree-undetermined:hover { + background-position: -199px -39px; +} +.jstree-default-dark-small .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark-small > .jstree-striped { + background-size: auto 36px; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -135px -39px; +} +.jstree-default-dark-small.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -103px -39px; +} +.jstree-default-dark-small.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -71px -39px; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -39px; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -39px; +} +.jstree-default-dark-small .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark-small > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark-small .jstree-file { + background: url("32px.png") -103px -71px no-repeat; +} +.jstree-default-dark-small .jstree-folder { + background: url("32px.png") -263px -7px no-repeat; +} +.jstree-default-dark-small > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark-small { + line-height: 18px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark-small .jstree-ok, +#jstree-dnd.jstree-default-dark-small .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark-small i { + background: transparent; + width: 18px; + height: 18px; + line-height: 18px; +} +#jstree-dnd.jstree-default-dark-small .jstree-ok { + background-position: -7px -71px; +} +#jstree-dnd.jstree-default-dark-small .jstree-er { + background-position: -39px -71px; +} +.jstree-default-dark-small .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark-small .jstree-ellipsis .jstree-anchor { + width: calc(100% - 23px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark-small .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large .jstree-node { + min-height: 32px; + line-height: 32px; + margin-left: 32px; + min-width: 32px; +} +.jstree-default-dark-large .jstree-anchor { + line-height: 32px; + height: 32px; +} +.jstree-default-dark-large .jstree-icon { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-dark-large .jstree-icon:empty { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + margin-right: 32px; +} +.jstree-default-dark-large .jstree-wholerow { + height: 32px; +} +.jstree-default-dark-large .jstree-node, +.jstree-default-dark-large .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark-large .jstree-node { + background-position: -288px 0px; + background-repeat: repeat-y; +} +.jstree-default-dark-large .jstree-last { + background: transparent; +} +.jstree-default-dark-large .jstree-open > .jstree-ocl { + background-position: -128px 0px; +} +.jstree-default-dark-large .jstree-closed > .jstree-ocl { + background-position: -96px 0px; +} +.jstree-default-dark-large .jstree-leaf > .jstree-ocl { + background-position: -64px 0px; +} +.jstree-default-dark-large .jstree-themeicon { + background-position: -256px 0px; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-node, +.jstree-default-dark-large > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px 0px; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px 0px; +} +.jstree-default-dark-large .jstree-disabled { + background: transparent; +} +.jstree-default-dark-large .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark-large .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark-large .jstree-checkbox { + background-position: -160px 0px; +} +.jstree-default-dark-large .jstree-checkbox:hover { + background-position: -160px -32px; +} +.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark-large .jstree-checked > .jstree-checkbox { + background-position: -224px 0px; +} +.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark-large .jstree-checked > .jstree-checkbox:hover { + background-position: -224px -32px; +} +.jstree-default-dark-large .jstree-anchor > .jstree-undetermined { + background-position: -192px 0px; +} +.jstree-default-dark-large .jstree-anchor > .jstree-undetermined:hover { + background-position: -192px -32px; +} +.jstree-default-dark-large .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark-large > .jstree-striped { + background-size: auto 64px; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -128px -32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -96px -32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -64px -32px; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px -32px; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px -32px; +} +.jstree-default-dark-large .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark-large > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark-large .jstree-file { + background: url("32px.png") -96px -64px no-repeat; +} +.jstree-default-dark-large .jstree-folder { + background: url("32px.png") -256px 0px no-repeat; +} +.jstree-default-dark-large > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark-large { + line-height: 32px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark-large .jstree-ok, +#jstree-dnd.jstree-default-dark-large .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark-large i { + background: transparent; + width: 32px; + height: 32px; + line-height: 32px; +} +#jstree-dnd.jstree-default-dark-large .jstree-ok { + background-position: 0px -64px; +} +#jstree-dnd.jstree-default-dark-large .jstree-er { + background-position: -32px -64px; +} +.jstree-default-dark-large .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark-large .jstree-ellipsis .jstree-anchor { + width: calc(100% - 37px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark-large .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} +@media (max-width: 768px) { + #jstree-dnd.jstree-dnd-responsive { + line-height: 40px; + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + #jstree-dnd.jstree-dnd-responsive > i { + background: transparent; + width: 40px; + height: 40px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-ok { + background-image: url("40px.png"); + background-position: 0 -200px; + background-size: 120px 240px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-er { + background-image: url("40px.png"); + background-position: -40px -200px; + background-size: 120px 240px; + } + #jstree-marker.jstree-dnd-responsive { + border-left-width: 10px; + border-top-width: 10px; + border-bottom-width: 10px; + margin-top: -10px; + } +} +@media (max-width: 768px) { + .jstree-default-dark-responsive { + /* + .jstree-open > .jstree-ocl, + .jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; } + */ + } + .jstree-default-dark-responsive .jstree-icon { + background-image: url("40px.png"); + } + .jstree-default-dark-responsive .jstree-node, + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-dark-responsive .jstree-node { + min-height: 40px; + line-height: 40px; + margin-left: 40px; + min-width: 40px; + white-space: nowrap; + } + .jstree-default-dark-responsive .jstree-anchor { + line-height: 40px; + height: 40px; + } + .jstree-default-dark-responsive .jstree-icon, + .jstree-default-dark-responsive .jstree-icon:empty { + width: 40px; + height: 40px; + line-height: 40px; + } + .jstree-default-dark-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-node { + margin-left: 0; + margin-right: 40px; + background: transparent; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; + } + .jstree-default-dark-responsive .jstree-ocl, + .jstree-default-dark-responsive .jstree-themeicon, + .jstree-default-dark-responsive .jstree-checkbox { + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl, + .jstree-default-dark-responsive.jstree-rtl .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-dark-responsive .jstree-open > .jstree-ocl { + background-position: 0 0px !important; + } + .jstree-default-dark-responsive .jstree-closed > .jstree-ocl { + background-position: 0 -40px !important; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -40px 0px !important; + } + .jstree-default-dark-responsive .jstree-themeicon { + background-position: -40px -40px; + } + .jstree-default-dark-responsive .jstree-checkbox, + .jstree-default-dark-responsive .jstree-checkbox:hover { + background-position: -40px -80px; + } + .jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, + .jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, + .jstree-default-dark-responsive .jstree-checked > .jstree-checkbox, + .jstree-default-dark-responsive .jstree-checked > .jstree-checkbox:hover { + background-position: 0 -80px; + } + .jstree-default-dark-responsive .jstree-anchor > .jstree-undetermined, + .jstree-default-dark-responsive .jstree-anchor > .jstree-undetermined:hover { + background-position: 0 -120px; + } + .jstree-default-dark-responsive .jstree-anchor { + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + .jstree-default-dark-responsive > .jstree-striped { + background: transparent; + } + .jstree-default-dark-responsive .jstree-wholerow { + border-top: 1px solid #666666; + border-bottom: 1px solid #000000; + background: #333333; + height: 40px; + } + .jstree-default-dark-responsive .jstree-wholerow-hovered { + background: #555555; + } + .jstree-default-dark-responsive .jstree-wholerow-clicked { + background: #5fa2db; + } + .jstree-default-dark-responsive .jstree-children .jstree-last > .jstree-wholerow { + box-shadow: inset 0 -6px 3px -5px #111111; + } + .jstree-default-dark-responsive .jstree-children .jstree-open > .jstree-wholerow { + box-shadow: inset 0 6px 3px -5px #111111; + border-top: 0; + } + .jstree-default-dark-responsive .jstree-children .jstree-open + .jstree-open { + box-shadow: none; + } + .jstree-default-dark-responsive .jstree-node, + .jstree-default-dark-responsive .jstree-icon, + .jstree-default-dark-responsive .jstree-node > .jstree-ocl, + .jstree-default-dark-responsive .jstree-themeicon, + .jstree-default-dark-responsive .jstree-checkbox { + background-image: url("40px.png"); + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-node { + background-position: -80px 0; + background-repeat: repeat-y; + } + .jstree-default-dark-responsive .jstree-last { + background: transparent; + } + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl { + background-position: -40px -120px; + } + .jstree-default-dark-responsive .jstree-last > .jstree-ocl { + background-position: -40px -160px; + } + .jstree-default-dark-responsive .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; + } + .jstree-default-dark-responsive .jstree-file { + background: url("40px.png") 0 -160px no-repeat; + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-folder { + background: url("40px.png") -40px -40px no-repeat; + background-size: 120px 240px; + } + .jstree-default-dark-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; + } +} +.jstree-default-dark { + background: #333; +} +.jstree-default-dark .jstree-anchor { + color: #999; + text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5); +} +.jstree-default-dark .jstree-clicked, +.jstree-default-dark .jstree-checked { + color: white; +} +.jstree-default-dark .jstree-hovered { + color: white; +} +#jstree-marker.jstree-default-dark { + border-left-color: #999; + background: transparent; +} +.jstree-default-dark .jstree-anchor > .jstree-icon { + opacity: 0.75; +} +.jstree-default-dark .jstree-clicked > .jstree-icon, +.jstree-default-dark .jstree-hovered > .jstree-icon, +.jstree-default-dark .jstree-checked > .jstree-icon { + opacity: 1; +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} diff --git a/civicrm/bower_components/jstree/dist/themes/default-dark/style.min.css b/civicrm/bower_components/jstree/dist/themes/default-dark/style.min.css new file mode 100644 index 0000000000000000000000000000000000000000..d9084d403c02dea6c1c4810943d5a1a941cbd897 --- /dev/null +++ b/civicrm/bower_components/jstree/dist/themes/default-dark/style.min.css @@ -0,0 +1 @@ +.jstree-node,.jstree-children,.jstree-container-ul{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;color:#000;white-space:nowrap;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:link,.jstree-anchor:visited,.jstree-anchor:hover,.jstree-anchor:active{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children{display:none}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree-no-icons .jstree-themeicon,.jstree-anchor>.jstree-themeicon-hidden{display:none}.jstree-hidden,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin-top:-2.7em;margin-left:-4px}.vakata-context .vakata-context-right ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-hover>a{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon,#jstree-dnd .jstree-copy{display:inline-block;text-decoration:none;margin:0 2px 0 0;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default-dark .jstree-node,.jstree-default-dark .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default-dark .jstree-anchor,.jstree-default-dark .jstree-animated,.jstree-default-dark .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default-dark .jstree-hovered{background:#555;border-radius:2px;box-shadow:inset 0 0 1px #555}.jstree-default-dark .jstree-context{background:#555;border-radius:2px;box-shadow:inset 0 0 1px #555}.jstree-default-dark .jstree-clicked{background:#5fa2db;border-radius:2px;box-shadow:inset 0 0 1px #666}.jstree-default-dark .jstree-no-icons .jstree-anchor>.jstree-themeicon{display:none}.jstree-default-dark .jstree-disabled{background:0 0;color:#666}.jstree-default-dark .jstree-disabled.jstree-hovered{background:0 0;box-shadow:none}.jstree-default-dark .jstree-disabled.jstree-clicked{background:#333}.jstree-default-dark .jstree-disabled>.jstree-icon{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-dark .jstree-search{font-style:italic;color:#fff;font-weight:700}.jstree-default-dark .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered{background:#555}.jstree-default-dark.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default-dark.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#555}.jstree-default-dark>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top repeat}.jstree-default-dark>.jstree-wholerow-ul .jstree-hovered,.jstree-default-dark>.jstree-wholerow-ul .jstree-clicked{background:0 0;box-shadow:none;border-radius:0}.jstree-default-dark .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default-dark .jstree-wholerow-hovered{background:#555}.jstree-default-dark .jstree-wholerow-clicked{background:#5fa2db;background:-webkit-linear-gradient(top,#5fa2db 0,#5fa2db 100%);background:linear-gradient(to bottom,#5fa2db 0,#5fa2db 100%)}.jstree-default-dark .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default-dark .jstree-anchor{line-height:24px;height:24px}.jstree-default-dark .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default-dark .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default-dark.jstree-rtl .jstree-node{margin-right:24px}.jstree-default-dark .jstree-wholerow{height:24px}.jstree-default-dark .jstree-node,.jstree-default-dark .jstree-icon{background-image:url(32px.png)}.jstree-default-dark .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default-dark .jstree-last{background:0 0}.jstree-default-dark .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default-dark .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default-dark .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default-dark .jstree-themeicon{background-position:-260px -4px}.jstree-default-dark>.jstree-no-dots .jstree-node,.jstree-default-dark>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default-dark>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default-dark .jstree-disabled{background:0 0}.jstree-default-dark .jstree-disabled.jstree-hovered{background:0 0}.jstree-default-dark .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-dark .jstree-checkbox{background-position:-164px -4px}.jstree-default-dark .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default-dark.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-dark .jstree-checked>.jstree-checkbox{background-position:-228px -4px}.jstree-default-dark.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-dark .jstree-checked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default-dark .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default-dark .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default-dark .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-dark>.jstree-striped{background-size:auto 48px}.jstree-default-dark.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default-dark.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default-dark.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default-dark.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default-dark.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-dark.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default-dark.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default-dark .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-dark>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default-dark .jstree-file{background:url(32px.png) -100px -68px no-repeat}.jstree-default-dark .jstree-folder{background:url(32px.png) -260px -4px no-repeat}.jstree-default-dark>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-dark{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default-dark .jstree-ok,#jstree-dnd.jstree-default-dark .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-dark i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default-dark .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default-dark .jstree-er{background-position:-36px -68px}.jstree-default-dark .jstree-ellipsis{overflow:hidden}.jstree-default-dark .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default-dark .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default-dark.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default-dark.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-dark-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-dark-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-dark-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-dark-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-dark-small .jstree-wholerow{height:18px}.jstree-default-dark-small .jstree-node,.jstree-default-dark-small .jstree-icon{background-image:url(32px.png)}.jstree-default-dark-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-dark-small .jstree-last{background:0 0}.jstree-default-dark-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-dark-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-dark-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-dark-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-dark-small>.jstree-no-dots .jstree-node,.jstree-default-dark-small>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-dark-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-dark-small .jstree-disabled{background:0 0}.jstree-default-dark-small .jstree-disabled.jstree-hovered{background:0 0}.jstree-default-dark-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-dark-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-dark-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-dark-small .jstree-checked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-dark-small .jstree-checked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-dark-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-dark-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-dark-small .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-dark-small>.jstree-striped{background-size:auto 36px}.jstree-default-dark-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default-dark-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-dark-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-dark-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-dark-small.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-dark-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-dark-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-dark-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-dark-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default-dark-small .jstree-file{background:url(32px.png) -103px -71px no-repeat}.jstree-default-dark-small .jstree-folder{background:url(32px.png) -263px -7px no-repeat}.jstree-default-dark-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-dark-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-dark-small .jstree-ok,#jstree-dnd.jstree-default-dark-small .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-dark-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-dark-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-dark-small .jstree-er{background-position:-39px -71px}.jstree-default-dark-small .jstree-ellipsis{overflow:hidden}.jstree-default-dark-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-dark-small .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default-dark-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-dark-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-dark-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-dark-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-dark-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-dark-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-dark-large .jstree-wholerow{height:32px}.jstree-default-dark-large .jstree-node,.jstree-default-dark-large .jstree-icon{background-image:url(32px.png)}.jstree-default-dark-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-dark-large .jstree-last{background:0 0}.jstree-default-dark-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-dark-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-dark-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-dark-large .jstree-themeicon{background-position:-256px 0}.jstree-default-dark-large>.jstree-no-dots .jstree-node,.jstree-default-dark-large>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-dark-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-dark-large .jstree-disabled{background:0 0}.jstree-default-dark-large .jstree-disabled.jstree-hovered{background:0 0}.jstree-default-dark-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-dark-large .jstree-checkbox{background-position:-160px 0}.jstree-default-dark-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-dark-large .jstree-checked>.jstree-checkbox{background-position:-224px 0}.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-dark-large .jstree-checked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-dark-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-dark-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-dark-large .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-dark-large>.jstree-striped{background-size:auto 64px}.jstree-default-dark-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default-dark-large.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-dark-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-dark-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-dark-large.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-dark-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-dark-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-dark-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-dark-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default-dark-large .jstree-file{background:url(32px.png) -96px -64px no-repeat}.jstree-default-dark-large .jstree-folder{background:url(32px.png) -256px 0 no-repeat}.jstree-default-dark-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-dark-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-dark-large .jstree-ok,#jstree-dnd.jstree-default-dark-large .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-dark-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-dark-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-dark-large .jstree-er{background-position:-32px -64px}.jstree-default-dark-large .jstree-ellipsis{overflow:hidden}.jstree-default-dark-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-dark-large .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default-dark-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-dark-large.jstree-rtl .jstree-last{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-image:url(40px.png);background-position:-40px -200px;background-size:120px 240px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}}@media (max-width:768px){.jstree-default-dark-responsive .jstree-icon{background-image:url(40px.png)}.jstree-default-dark-responsive .jstree-node,.jstree-default-dark-responsive .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-responsive .jstree-node{min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-dark-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-dark-responsive .jstree-icon,.jstree-default-dark-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-dark-responsive>.jstree-container-ul>.jstree-node{margin-left:0}.jstree-default-dark-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-dark-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-dark-responsive .jstree-ocl,.jstree-default-dark-responsive .jstree-themeicon,.jstree-default-dark-responsive .jstree-checkbox{background-size:120px 240px}.jstree-default-dark-responsive .jstree-leaf>.jstree-ocl,.jstree-default-dark-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-dark-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-dark-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-dark-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-dark-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-dark-responsive .jstree-checkbox,.jstree-default-dark-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-dark-responsive .jstree-checked>.jstree-checkbox,.jstree-default-dark-responsive .jstree-checked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-dark-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-dark-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-dark-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-dark-responsive>.jstree-striped{background:0 0}.jstree-default-dark-responsive .jstree-wholerow{border-top:1px solid #666;border-bottom:1px solid #000;background:#333;height:40px}.jstree-default-dark-responsive .jstree-wholerow-hovered{background:#555}.jstree-default-dark-responsive .jstree-wholerow-clicked{background:#5fa2db}.jstree-default-dark-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #111}.jstree-default-dark-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #111;border-top:0}.jstree-default-dark-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-dark-responsive .jstree-node,.jstree-default-dark-responsive .jstree-icon,.jstree-default-dark-responsive .jstree-node>.jstree-ocl,.jstree-default-dark-responsive .jstree-themeicon,.jstree-default-dark-responsive .jstree-checkbox{background-image:url(40px.png);background-size:120px 240px}.jstree-default-dark-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-dark-responsive .jstree-last{background:0 0}.jstree-default-dark-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-dark-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-dark-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-dark-responsive .jstree-file{background:url(40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-dark-responsive .jstree-folder{background:url(40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-dark-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}}.jstree-default-dark{background:#333}.jstree-default-dark .jstree-anchor{color:#999;text-shadow:1px 1px 0 rgba(0,0,0,.5)}.jstree-default-dark .jstree-clicked,.jstree-default-dark .jstree-checked{color:#fff}.jstree-default-dark .jstree-hovered{color:#fff}#jstree-marker.jstree-default-dark{border-left-color:#999;background:0 0}.jstree-default-dark .jstree-anchor>.jstree-icon{opacity:.75}.jstree-default-dark .jstree-clicked>.jstree-icon,.jstree-default-dark .jstree-hovered>.jstree-icon,.jstree-default-dark .jstree-checked>.jstree-icon{opacity:1}.jstree-default-dark.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default-dark.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-dark-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-dark-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-dark-large.jstree-rtl .jstree-last{background:0 0} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/dist/themes/default-dark/throbber.gif b/civicrm/bower_components/jstree/dist/themes/default-dark/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd75035ce8086b233c62c3775de4696007ba7950 Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default-dark/throbber.gif differ diff --git a/civicrm/bower_components/jstree/dist/themes/default/32px.png b/civicrm/bower_components/jstree/dist/themes/default/32px.png new file mode 100644 index 0000000000000000000000000000000000000000..15327152481789306eadef88393cd1c748dc31a7 Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default/32px.png differ diff --git a/civicrm/bower_components/jstree/dist/themes/default/40px.png b/civicrm/bower_components/jstree/dist/themes/default/40px.png new file mode 100644 index 0000000000000000000000000000000000000000..1959347aea041d75a58d0584ea7ec51714797983 Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default/40px.png differ diff --git a/civicrm/bower_components/jstree/dist/themes/default/style.css b/civicrm/bower_components/jstree/dist/themes/default/style.css new file mode 100644 index 0000000000000000000000000000000000000000..616be241beada11266824974dbfa2811d3f8d8bc --- /dev/null +++ b/civicrm/bower_components/jstree/dist/themes/default/style.css @@ -0,0 +1,1102 @@ +/* jsTree default theme */ +.jstree-node, +.jstree-children, +.jstree-container-ul { + display: block; + margin: 0; + padding: 0; + list-style-type: none; + list-style-image: none; +} +.jstree-node { + white-space: nowrap; +} +.jstree-anchor { + display: inline-block; + color: black; + white-space: nowrap; + padding: 0 4px 0 1px; + margin: 0; + vertical-align: top; +} +.jstree-anchor:focus { + outline: 0; +} +.jstree-anchor, +.jstree-anchor:link, +.jstree-anchor:visited, +.jstree-anchor:hover, +.jstree-anchor:active { + text-decoration: none; + color: inherit; +} +.jstree-icon { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-icon:empty { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-ocl { + cursor: pointer; +} +.jstree-leaf > .jstree-ocl { + cursor: default; +} +.jstree .jstree-open > .jstree-children { + display: block; +} +.jstree .jstree-closed > .jstree-children, +.jstree .jstree-leaf > .jstree-children { + display: none; +} +.jstree-anchor > .jstree-themeicon { + margin-right: 2px; +} +.jstree-no-icons .jstree-themeicon, +.jstree-anchor > .jstree-themeicon-hidden { + display: none; +} +.jstree-hidden, +.jstree-node.jstree-hidden { + display: none; +} +.jstree-rtl .jstree-anchor { + padding: 0 1px 0 4px; +} +.jstree-rtl .jstree-anchor > .jstree-themeicon { + margin-left: 2px; + margin-right: 0; +} +.jstree-rtl .jstree-node { + margin-left: 0; +} +.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; +} +.jstree-wholerow-ul { + position: relative; + display: inline-block; + min-width: 100%; +} +.jstree-wholerow-ul .jstree-leaf > .jstree-ocl { + cursor: pointer; +} +.jstree-wholerow-ul .jstree-anchor, +.jstree-wholerow-ul .jstree-icon { + position: relative; +} +.jstree-wholerow-ul .jstree-wholerow { + width: 100%; + cursor: pointer; + position: absolute; + left: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.vakata-context { + display: none; +} +.vakata-context, +.vakata-context ul { + margin: 0; + padding: 2px; + position: absolute; + background: #f5f5f5; + border: 1px solid #979797; + box-shadow: 2px 2px 2px #999999; +} +.vakata-context ul { + list-style: none; + left: 100%; + margin-top: -2.7em; + margin-left: -4px; +} +.vakata-context .vakata-context-right ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context li { + list-style: none; +} +.vakata-context li > a { + display: block; + padding: 0 2em 0 2em; + text-decoration: none; + width: auto; + color: black; + white-space: nowrap; + line-height: 2.4em; + text-shadow: 1px 1px 0 white; + border-radius: 1px; +} +.vakata-context li > a:hover { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); + background-position: right center; + background-repeat: no-repeat; +} +.vakata-context li > a:focus { + outline: 0; +} +.vakata-context .vakata-context-hover > a { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context .vakata-context-separator > a, +.vakata-context .vakata-context-separator > a:hover { + background: white; + border: 0; + border-top: 1px solid #e2e3e3; + height: 1px; + min-height: 1px; + max-height: 1px; + padding: 0; + margin: 0 0 0 2.4em; + border-left: 1px solid #e0e0e0; + text-shadow: 0 0 0 transparent; + box-shadow: 0 0 0 transparent; + border-radius: 0; +} +.vakata-context .vakata-contextmenu-disabled a, +.vakata-context .vakata-contextmenu-disabled a:hover { + color: silver; + background-color: transparent; + border: 0; + box-shadow: 0 0 0; +} +.vakata-context li > a > i { + text-decoration: none; + display: inline-block; + width: 2.4em; + height: 2.4em; + background: transparent; + margin: 0 0 0 -2em; + vertical-align: top; + text-align: center; + line-height: 2.4em; +} +.vakata-context li > a > i:empty { + width: 2.4em; + line-height: 2.4em; +} +.vakata-context li > a .vakata-contextmenu-sep { + display: inline-block; + width: 1px; + height: 2.4em; + background: white; + margin: 0 0.5em 0 0; + border-left: 1px solid #e2e3e3; +} +.vakata-context .vakata-contextmenu-shortcut { + font-size: 0.8em; + color: silver; + opacity: 0.5; + display: none; +} +.vakata-context-rtl ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context-rtl li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); + background-position: left center; + background-repeat: no-repeat; +} +.vakata-context-rtl .vakata-context-separator > a { + margin: 0 2.4em 0 0; + border-left: 0; + border-right: 1px solid #e2e3e3; +} +.vakata-context-rtl .vakata-context-left ul { + right: auto; + left: 100%; + margin-left: -4px; + margin-right: auto; +} +.vakata-context-rtl li > a > i { + margin: 0 -2em 0 0; +} +.vakata-context-rtl li > a .vakata-contextmenu-sep { + margin: 0 0 0 0.5em; + border-left-color: white; + background: #e2e3e3; +} +#jstree-marker { + position: absolute; + top: 0; + left: 0; + margin: -5px 0 0 0; + padding: 0; + border-right: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid; + width: 0; + height: 0; + font-size: 0; + line-height: 0; +} +#jstree-dnd { + line-height: 16px; + margin: 0; + padding: 4px; +} +#jstree-dnd .jstree-icon, +#jstree-dnd .jstree-copy { + display: inline-block; + text-decoration: none; + margin: 0 2px 0 0; + padding: 0; + width: 16px; + height: 16px; +} +#jstree-dnd .jstree-ok { + background: green; +} +#jstree-dnd .jstree-er { + background: red; +} +#jstree-dnd .jstree-copy { + margin: 0 2px 0 2px; +} +.jstree-default .jstree-node, +.jstree-default .jstree-icon { + background-repeat: no-repeat; + background-color: transparent; +} +.jstree-default .jstree-anchor, +.jstree-default .jstree-animated, +.jstree-default .jstree-wholerow { + transition: background-color 0.15s, box-shadow 0.15s; +} +.jstree-default .jstree-hovered { + background: #e7f4f9; + border-radius: 2px; + box-shadow: inset 0 0 1px #cccccc; +} +.jstree-default .jstree-context { + background: #e7f4f9; + border-radius: 2px; + box-shadow: inset 0 0 1px #cccccc; +} +.jstree-default .jstree-clicked { + background: #beebff; + border-radius: 2px; + box-shadow: inset 0 0 1px #999999; +} +.jstree-default .jstree-no-icons .jstree-anchor > .jstree-themeicon { + display: none; +} +.jstree-default .jstree-disabled { + background: transparent; + color: #666666; +} +.jstree-default .jstree-disabled.jstree-hovered { + background: transparent; + box-shadow: none; +} +.jstree-default .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default .jstree-disabled > .jstree-icon { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default .jstree-search { + font-style: italic; + color: #8b0000; + font-weight: bold; +} +.jstree-default .jstree-no-checkboxes .jstree-checkbox { + display: none !important; +} +.jstree-default.jstree-checkbox-no-clicked .jstree-clicked { + background: transparent; + box-shadow: none; +} +.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered { + background: #e7f4f9; +} +.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked { + background: transparent; +} +.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered { + background: #e7f4f9; +} +.jstree-default > .jstree-striped { + min-width: 100%; + display: inline-block; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; +} +.jstree-default > .jstree-wholerow-ul .jstree-hovered, +.jstree-default > .jstree-wholerow-ul .jstree-clicked { + background: transparent; + box-shadow: none; + border-radius: 0; +} +.jstree-default .jstree-wholerow { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.jstree-default .jstree-wholerow-hovered { + background: #e7f4f9; +} +.jstree-default .jstree-wholerow-clicked { + background: #beebff; + background: -webkit-linear-gradient(top, #beebff 0%, #a8e4ff 100%); + background: linear-gradient(to bottom, #beebff 0%, #a8e4ff 100%); +} +.jstree-default .jstree-node { + min-height: 24px; + line-height: 24px; + margin-left: 24px; + min-width: 24px; +} +.jstree-default .jstree-anchor { + line-height: 24px; + height: 24px; +} +.jstree-default .jstree-icon { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default .jstree-icon:empty { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default.jstree-rtl .jstree-node { + margin-right: 24px; +} +.jstree-default .jstree-wholerow { + height: 24px; +} +.jstree-default .jstree-node, +.jstree-default .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default .jstree-node { + background-position: -292px -4px; + background-repeat: repeat-y; +} +.jstree-default .jstree-last { + background: transparent; +} +.jstree-default .jstree-open > .jstree-ocl { + background-position: -132px -4px; +} +.jstree-default .jstree-closed > .jstree-ocl { + background-position: -100px -4px; +} +.jstree-default .jstree-leaf > .jstree-ocl { + background-position: -68px -4px; +} +.jstree-default .jstree-themeicon { + background-position: -260px -4px; +} +.jstree-default > .jstree-no-dots .jstree-node, +.jstree-default > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -4px; +} +.jstree-default > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -4px; +} +.jstree-default .jstree-disabled { + background: transparent; +} +.jstree-default .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default .jstree-checkbox { + background-position: -164px -4px; +} +.jstree-default .jstree-checkbox:hover { + background-position: -164px -36px; +} +.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default .jstree-checked > .jstree-checkbox { + background-position: -228px -4px; +} +.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default .jstree-checked > .jstree-checkbox:hover { + background-position: -228px -36px; +} +.jstree-default .jstree-anchor > .jstree-undetermined { + background-position: -196px -4px; +} +.jstree-default .jstree-anchor > .jstree-undetermined:hover { + background-position: -196px -36px; +} +.jstree-default .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default > .jstree-striped { + background-size: auto 48px; +} +.jstree-default.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -132px -36px; +} +.jstree-default.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -100px -36px; +} +.jstree-default.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -68px -36px; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -36px; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -36px; +} +.jstree-default .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default .jstree-file { + background: url("32px.png") -100px -68px no-repeat; +} +.jstree-default .jstree-folder { + background: url("32px.png") -260px -4px no-repeat; +} +.jstree-default > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default { + line-height: 24px; + padding: 0 4px; +} +#jstree-dnd.jstree-default .jstree-ok, +#jstree-dnd.jstree-default .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default i { + background: transparent; + width: 24px; + height: 24px; + line-height: 24px; +} +#jstree-dnd.jstree-default .jstree-ok { + background-position: -4px -68px; +} +#jstree-dnd.jstree-default .jstree-er { + background-position: -36px -68px; +} +.jstree-default .jstree-ellipsis { + overflow: hidden; +} +.jstree-default .jstree-ellipsis .jstree-anchor { + width: calc(100% - 29px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-small .jstree-node { + min-height: 18px; + line-height: 18px; + margin-left: 18px; + min-width: 18px; +} +.jstree-default-small .jstree-anchor { + line-height: 18px; + height: 18px; +} +.jstree-default-small .jstree-icon { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-small .jstree-icon:empty { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-small.jstree-rtl .jstree-node { + margin-right: 18px; +} +.jstree-default-small .jstree-wholerow { + height: 18px; +} +.jstree-default-small .jstree-node, +.jstree-default-small .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-small .jstree-node { + background-position: -295px -7px; + background-repeat: repeat-y; +} +.jstree-default-small .jstree-last { + background: transparent; +} +.jstree-default-small .jstree-open > .jstree-ocl { + background-position: -135px -7px; +} +.jstree-default-small .jstree-closed > .jstree-ocl { + background-position: -103px -7px; +} +.jstree-default-small .jstree-leaf > .jstree-ocl { + background-position: -71px -7px; +} +.jstree-default-small .jstree-themeicon { + background-position: -263px -7px; +} +.jstree-default-small > .jstree-no-dots .jstree-node, +.jstree-default-small > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-small > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -7px; +} +.jstree-default-small > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -7px; +} +.jstree-default-small .jstree-disabled { + background: transparent; +} +.jstree-default-small .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-small .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-small .jstree-checkbox { + background-position: -167px -7px; +} +.jstree-default-small .jstree-checkbox:hover { + background-position: -167px -39px; +} +.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-small .jstree-checked > .jstree-checkbox { + background-position: -231px -7px; +} +.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-small .jstree-checked > .jstree-checkbox:hover { + background-position: -231px -39px; +} +.jstree-default-small .jstree-anchor > .jstree-undetermined { + background-position: -199px -7px; +} +.jstree-default-small .jstree-anchor > .jstree-undetermined:hover { + background-position: -199px -39px; +} +.jstree-default-small .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-small > .jstree-striped { + background-size: auto 36px; +} +.jstree-default-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-small.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -135px -39px; +} +.jstree-default-small.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -103px -39px; +} +.jstree-default-small.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -71px -39px; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -39px; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -39px; +} +.jstree-default-small .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-small > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-small .jstree-file { + background: url("32px.png") -103px -71px no-repeat; +} +.jstree-default-small .jstree-folder { + background: url("32px.png") -263px -7px no-repeat; +} +.jstree-default-small > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-small { + line-height: 18px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-small .jstree-ok, +#jstree-dnd.jstree-default-small .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-small i { + background: transparent; + width: 18px; + height: 18px; + line-height: 18px; +} +#jstree-dnd.jstree-default-small .jstree-ok { + background-position: -7px -71px; +} +#jstree-dnd.jstree-default-small .jstree-er { + background-position: -39px -71px; +} +.jstree-default-small .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-small .jstree-ellipsis .jstree-anchor { + width: calc(100% - 23px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-small .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-large .jstree-node { + min-height: 32px; + line-height: 32px; + margin-left: 32px; + min-width: 32px; +} +.jstree-default-large .jstree-anchor { + line-height: 32px; + height: 32px; +} +.jstree-default-large .jstree-icon { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-large .jstree-icon:empty { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-large.jstree-rtl .jstree-node { + margin-right: 32px; +} +.jstree-default-large .jstree-wholerow { + height: 32px; +} +.jstree-default-large .jstree-node, +.jstree-default-large .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-large .jstree-node { + background-position: -288px 0px; + background-repeat: repeat-y; +} +.jstree-default-large .jstree-last { + background: transparent; +} +.jstree-default-large .jstree-open > .jstree-ocl { + background-position: -128px 0px; +} +.jstree-default-large .jstree-closed > .jstree-ocl { + background-position: -96px 0px; +} +.jstree-default-large .jstree-leaf > .jstree-ocl { + background-position: -64px 0px; +} +.jstree-default-large .jstree-themeicon { + background-position: -256px 0px; +} +.jstree-default-large > .jstree-no-dots .jstree-node, +.jstree-default-large > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-large > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px 0px; +} +.jstree-default-large > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px 0px; +} +.jstree-default-large .jstree-disabled { + background: transparent; +} +.jstree-default-large .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-large .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-large .jstree-checkbox { + background-position: -160px 0px; +} +.jstree-default-large .jstree-checkbox:hover { + background-position: -160px -32px; +} +.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-large .jstree-checked > .jstree-checkbox { + background-position: -224px 0px; +} +.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-large .jstree-checked > .jstree-checkbox:hover { + background-position: -224px -32px; +} +.jstree-default-large .jstree-anchor > .jstree-undetermined { + background-position: -192px 0px; +} +.jstree-default-large .jstree-anchor > .jstree-undetermined:hover { + background-position: -192px -32px; +} +.jstree-default-large .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-large > .jstree-striped { + background-size: auto 64px; +} +.jstree-default-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-large.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-large.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -128px -32px; +} +.jstree-default-large.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -96px -32px; +} +.jstree-default-large.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -64px -32px; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px -32px; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px -32px; +} +.jstree-default-large .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-large > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-large .jstree-file { + background: url("32px.png") -96px -64px no-repeat; +} +.jstree-default-large .jstree-folder { + background: url("32px.png") -256px 0px no-repeat; +} +.jstree-default-large > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-large { + line-height: 32px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-large .jstree-ok, +#jstree-dnd.jstree-default-large .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-large i { + background: transparent; + width: 32px; + height: 32px; + line-height: 32px; +} +#jstree-dnd.jstree-default-large .jstree-ok { + background-position: 0px -64px; +} +#jstree-dnd.jstree-default-large .jstree-er { + background-position: -32px -64px; +} +.jstree-default-large .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-large .jstree-ellipsis .jstree-anchor { + width: calc(100% - 37px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-large .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-large.jstree-rtl .jstree-last { + background: transparent; +} +@media (max-width: 768px) { + #jstree-dnd.jstree-dnd-responsive { + line-height: 40px; + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + #jstree-dnd.jstree-dnd-responsive > i { + background: transparent; + width: 40px; + height: 40px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-ok { + background-image: url("40px.png"); + background-position: 0 -200px; + background-size: 120px 240px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-er { + background-image: url("40px.png"); + background-position: -40px -200px; + background-size: 120px 240px; + } + #jstree-marker.jstree-dnd-responsive { + border-left-width: 10px; + border-top-width: 10px; + border-bottom-width: 10px; + margin-top: -10px; + } +} +@media (max-width: 768px) { + .jstree-default-responsive { + /* + .jstree-open > .jstree-ocl, + .jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; } + */ + } + .jstree-default-responsive .jstree-icon { + background-image: url("40px.png"); + } + .jstree-default-responsive .jstree-node, + .jstree-default-responsive .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-responsive .jstree-node { + min-height: 40px; + line-height: 40px; + margin-left: 40px; + min-width: 40px; + white-space: nowrap; + } + .jstree-default-responsive .jstree-anchor { + line-height: 40px; + height: 40px; + } + .jstree-default-responsive .jstree-icon, + .jstree-default-responsive .jstree-icon:empty { + width: 40px; + height: 40px; + line-height: 40px; + } + .jstree-default-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + } + .jstree-default-responsive.jstree-rtl .jstree-node { + margin-left: 0; + margin-right: 40px; + background: transparent; + } + .jstree-default-responsive.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; + } + .jstree-default-responsive .jstree-ocl, + .jstree-default-responsive .jstree-themeicon, + .jstree-default-responsive .jstree-checkbox { + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-leaf > .jstree-ocl, + .jstree-default-responsive.jstree-rtl .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-responsive .jstree-open > .jstree-ocl { + background-position: 0 0px !important; + } + .jstree-default-responsive .jstree-closed > .jstree-ocl { + background-position: 0 -40px !important; + } + .jstree-default-responsive.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -40px 0px !important; + } + .jstree-default-responsive .jstree-themeicon { + background-position: -40px -40px; + } + .jstree-default-responsive .jstree-checkbox, + .jstree-default-responsive .jstree-checkbox:hover { + background-position: -40px -80px; + } + .jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, + .jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, + .jstree-default-responsive .jstree-checked > .jstree-checkbox, + .jstree-default-responsive .jstree-checked > .jstree-checkbox:hover { + background-position: 0 -80px; + } + .jstree-default-responsive .jstree-anchor > .jstree-undetermined, + .jstree-default-responsive .jstree-anchor > .jstree-undetermined:hover { + background-position: 0 -120px; + } + .jstree-default-responsive .jstree-anchor { + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + .jstree-default-responsive > .jstree-striped { + background: transparent; + } + .jstree-default-responsive .jstree-wholerow { + border-top: 1px solid rgba(255, 255, 255, 0.7); + border-bottom: 1px solid rgba(64, 64, 64, 0.2); + background: #ebebeb; + height: 40px; + } + .jstree-default-responsive .jstree-wholerow-hovered { + background: #e7f4f9; + } + .jstree-default-responsive .jstree-wholerow-clicked { + background: #beebff; + } + .jstree-default-responsive .jstree-children .jstree-last > .jstree-wholerow { + box-shadow: inset 0 -6px 3px -5px #666666; + } + .jstree-default-responsive .jstree-children .jstree-open > .jstree-wholerow { + box-shadow: inset 0 6px 3px -5px #666666; + border-top: 0; + } + .jstree-default-responsive .jstree-children .jstree-open + .jstree-open { + box-shadow: none; + } + .jstree-default-responsive .jstree-node, + .jstree-default-responsive .jstree-icon, + .jstree-default-responsive .jstree-node > .jstree-ocl, + .jstree-default-responsive .jstree-themeicon, + .jstree-default-responsive .jstree-checkbox { + background-image: url("40px.png"); + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-node { + background-position: -80px 0; + background-repeat: repeat-y; + } + .jstree-default-responsive .jstree-last { + background: transparent; + } + .jstree-default-responsive .jstree-leaf > .jstree-ocl { + background-position: -40px -120px; + } + .jstree-default-responsive .jstree-last > .jstree-ocl { + background-position: -40px -160px; + } + .jstree-default-responsive .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; + } + .jstree-default-responsive .jstree-file { + background: url("40px.png") 0 -160px no-repeat; + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-folder { + background: url("40px.png") -40px -40px no-repeat; + background-size: 120px 240px; + } + .jstree-default-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; + } +} diff --git a/civicrm/bower_components/jstree/dist/themes/default/style.min.css b/civicrm/bower_components/jstree/dist/themes/default/style.min.css new file mode 100644 index 0000000000000000000000000000000000000000..a76f15c09464f07076ee5748c8509d18ebd8fc6c --- /dev/null +++ b/civicrm/bower_components/jstree/dist/themes/default/style.min.css @@ -0,0 +1 @@ +.jstree-node,.jstree-children,.jstree-container-ul{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;color:#000;white-space:nowrap;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:link,.jstree-anchor:visited,.jstree-anchor:hover,.jstree-anchor:active{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children{display:none}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree-no-icons .jstree-themeicon,.jstree-anchor>.jstree-themeicon-hidden{display:none}.jstree-hidden,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin-top:-2.7em;margin-left:-4px}.vakata-context .vakata-context-right ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-hover>a{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon,#jstree-dnd .jstree-copy{display:inline-block;text-decoration:none;margin:0 2px 0 0;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default .jstree-node,.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-context{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon{display:none}.jstree-default .jstree-disabled{background:0 0;color:#666}.jstree-default .jstree-disabled.jstree-hovered{background:0 0;box-shadow:none}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:700}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top repeat}.jstree-default>.jstree-wholerow-ul .jstree-hovered,.jstree-default>.jstree-wholerow-ul .jstree-clicked{background:0 0;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top,#beebff 0,#a8e4ff 100%);background:linear-gradient(to bottom,#beebff 0,#a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}.jstree-default .jstree-node,.jstree-default .jstree-icon{background-image:url(32px.png)}.jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default .jstree-last{background:0 0}.jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default .jstree-themeicon{background-position:-260px -4px}.jstree-default>.jstree-no-dots .jstree-node,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default .jstree-disabled{background:0 0}.jstree-default .jstree-disabled.jstree-hovered{background:0 0}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-checkbox{background-position:-164px -4px}.jstree-default .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default .jstree-checked>.jstree-checkbox{background-position:-228px -4px}.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default .jstree-checked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default>.jstree-striped{background-size:auto 48px}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default .jstree-file{background:url(32px.png) -100px -68px no-repeat}.jstree-default .jstree-folder{background:url(32px.png) -260px -4px no-repeat}.jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default .jstree-ok,#jstree-dnd.jstree-default .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px}.jstree-default .jstree-ellipsis{overflow:hidden}.jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-small .jstree-wholerow{height:18px}.jstree-default-small .jstree-node,.jstree-default-small .jstree-icon{background-image:url(32px.png)}.jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-small .jstree-last{background:0 0}.jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-small>.jstree-no-dots .jstree-node,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-small .jstree-disabled{background:0 0}.jstree-default-small .jstree-disabled.jstree-hovered{background:0 0}.jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-small .jstree-checked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-small .jstree-checked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-small>.jstree-striped{background-size:auto 36px}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default-small .jstree-file{background:url(32px.png) -103px -71px no-repeat}.jstree-default-small .jstree-folder{background:url(32px.png) -263px -7px no-repeat}.jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-small .jstree-ok,#jstree-dnd.jstree-default-small .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px}.jstree-default-small .jstree-ellipsis{overflow:hidden}.jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-small .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-large .jstree-wholerow{height:32px}.jstree-default-large .jstree-node,.jstree-default-large .jstree-icon{background-image:url(32px.png)}.jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-large .jstree-last{background:0 0}.jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-large .jstree-themeicon{background-position:-256px 0}.jstree-default-large>.jstree-no-dots .jstree-node,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-large .jstree-disabled{background:0 0}.jstree-default-large .jstree-disabled.jstree-hovered{background:0 0}.jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-large .jstree-checkbox{background-position:-160px 0}.jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-large .jstree-checked>.jstree-checkbox{background-position:-224px 0}.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-large .jstree-checked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-large>.jstree-striped{background-size:auto 64px}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==);background-position:100% 1px;background-repeat:repeat-y}.jstree-default-large.jstree-rtl .jstree-last{background:0 0}.jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(throbber.gif) center center no-repeat}.jstree-default-large .jstree-file{background:url(32px.png) -96px -64px no-repeat}.jstree-default-large .jstree-folder{background:url(32px.png) -256px 0 no-repeat}.jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-large .jstree-ok,#jstree-dnd.jstree-default-large .jstree-er{background-image:url(32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px}.jstree-default-large .jstree-ellipsis{overflow:hidden}.jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-large .jstree-ellipsis.jstree-no-icons .jstree-anchor{width:calc(100% - 5px)}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-large.jstree-rtl .jstree-last{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-image:url(40px.png);background-position:-40px -200px;background-size:120px 240px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}}@media (max-width:768px){.jstree-default-responsive .jstree-icon{background-image:url(40px.png)}.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-node{min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0}.jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-responsive .jstree-ocl,.jstree-default-responsive .jstree-themeicon,.jstree-default-responsive .jstree-checkbox{background-size:120px 240px}.jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-responsive>.jstree-striped{background:0 0}.jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,.7);border-bottom:1px solid rgba(64,64,64,.2);background:#ebebeb;height:40px}.jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default-responsive .jstree-wholerow-clicked{background:#beebff}.jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666}.jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666;border-top:0}.jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon,.jstree-default-responsive .jstree-checkbox{background-image:url(40px.png);background-size:120px 240px}.jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-responsive .jstree-last{background:0 0}.jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-responsive .jstree-file{background:url(40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-responsive .jstree-folder{background:url(40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/dist/themes/default/throbber.gif b/civicrm/bower_components/jstree/dist/themes/default/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b5b2fde42f8ea14e6981339196a9d62b681d79e Binary files /dev/null and b/civicrm/bower_components/jstree/dist/themes/default/throbber.gif differ diff --git a/civicrm/bower_components/jstree/src/intro.js b/civicrm/bower_components/jstree/src/intro.js new file mode 100644 index 0000000000000000000000000000000000000000..5c95a5cdfb6bf2dbf4ce1f744515a87060f39b60 --- /dev/null +++ b/civicrm/bower_components/jstree/src/intro.js @@ -0,0 +1,14 @@ +/*globals jQuery, define, module, exports, require, window, document, postMessage */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else if(typeof module !== 'undefined' && module.exports) { + module.exports = factory(require('jquery')); + } + else { + factory(jQuery); + } +}(function ($, undefined) { + "use strict"; diff --git a/civicrm/bower_components/jstree/src/jstree.changed.js b/civicrm/bower_components/jstree/src/jstree.changed.js new file mode 100644 index 0000000000000000000000000000000000000000..be8cfd7d128f2eac8ded8410c521a6d495ccfc4d --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.changed.js @@ -0,0 +1,69 @@ +/** + * ### Changed plugin + * + * This plugin adds more information to the `changed.jstree` event. The new data is contained in the `changed` event data property, and contains a lists of `selected` and `deselected` nodes. + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.changed', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.changed) { return; } + + $.jstree.plugins.changed = function (options, parent) { + var last = []; + this.trigger = function (ev, data) { + var i, j; + if(!data) { + data = {}; + } + if(ev.replace('.jstree','') === 'changed') { + data.changed = { selected : [], deselected : [] }; + var tmp = {}; + for(i = 0, j = last.length; i < j; i++) { + tmp[last[i]] = 1; + } + for(i = 0, j = data.selected.length; i < j; i++) { + if(!tmp[data.selected[i]]) { + data.changed.selected.push(data.selected[i]); + } + else { + tmp[data.selected[i]] = 2; + } + } + for(i = 0, j = last.length; i < j; i++) { + if(tmp[last[i]] === 1) { + data.changed.deselected.push(last[i]); + } + } + last = data.selected.slice(); + } + /** + * triggered when selection changes (the "changed" plugin enhances the original event with more data) + * @event + * @name changed.jstree + * @param {Object} node + * @param {Object} action the action that caused the selection to change + * @param {Array} selected the current selection + * @param {Object} changed an object containing two properties `selected` and `deselected` - both arrays of node IDs, which were selected or deselected since the last changed event + * @param {Object} event the event (if any) that triggered this changed event + * @plugin changed + */ + parent.trigger.call(this, ev, data); + }; + this.refresh = function (skip_loading, forget_state) { + last = []; + return parent.refresh.apply(this, arguments); + }; + }; +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.checkbox.js b/civicrm/bower_components/jstree/src/jstree.checkbox.js new file mode 100644 index 0000000000000000000000000000000000000000..5dd9837d7501196e945af8ffbbc48c4309cfaf9d --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.checkbox.js @@ -0,0 +1,871 @@ +/** + * ### Checkbox plugin + * + * This plugin renders checkbox icons in front of each node, making multiple selection much easier. + * It also supports tri-state behavior, meaning that if a node has a few of its children checked it will be rendered as undetermined, and state will be propagated up. + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.checkbox', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.checkbox) { return; } + + var _i = document.createElement('I'); + _i.className = 'jstree-icon jstree-checkbox'; + _i.setAttribute('role', 'presentation'); + /** + * stores all defaults for the checkbox plugin + * @name $.jstree.defaults.checkbox + * @plugin checkbox + */ + $.jstree.defaults.checkbox = { + /** + * a boolean indicating if checkboxes should be visible (can be changed at a later time using `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`. + * @name $.jstree.defaults.checkbox.visible + * @plugin checkbox + */ + visible : true, + /** + * a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to `true`. + * @name $.jstree.defaults.checkbox.three_state + * @plugin checkbox + */ + three_state : true, + /** + * a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`. + * @name $.jstree.defaults.checkbox.whole_node + * @plugin checkbox + */ + whole_node : true, + /** + * a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`. + * @name $.jstree.defaults.checkbox.keep_selected_style + * @plugin checkbox + */ + keep_selected_style : true, + /** + * This setting controls how cascading and undetermined nodes are applied. + * If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled, if 'undetermined' is in the string - undetermined nodes will be used. + * If `three_state` is set to `true` this setting is automatically set to 'up+down+undetermined'. Defaults to ''. + * @name $.jstree.defaults.checkbox.cascade + * @plugin checkbox + */ + cascade : '', + /** + * This setting controls if checkbox are bound to the general tree selection or to an internal array maintained by the checkbox plugin. Defaults to `true`, only set to `false` if you know exactly what you are doing. + * @name $.jstree.defaults.checkbox.tie_selection + * @plugin checkbox + */ + tie_selection : true + }; + $.jstree.plugins.checkbox = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this._data.checkbox.uto = false; + this._data.checkbox.selected = []; + if(this.settings.checkbox.three_state) { + this.settings.checkbox.cascade = 'up+down+undetermined'; + } + this.element + .on("init.jstree", $.proxy(function () { + this._data.checkbox.visible = this.settings.checkbox.visible; + if(!this.settings.checkbox.keep_selected_style) { + this.element.addClass('jstree-checkbox-no-clicked'); + } + if(this.settings.checkbox.tie_selection) { + this.element.addClass('jstree-checkbox-selection'); + } + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ](); + }, this)); + if(this.settings.checkbox.cascade.indexOf('undetermined') !== -1) { + this.element + .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () { + // only if undetermined is in setting + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + }, this)); + } + if(!this.settings.checkbox.tie_selection) { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + p = m[data.parent], + dpc = data.nodes, + i, j; + for(i = 0, j = dpc.length; i < j; i++) { + m[dpc[i]].state.checked = m[dpc[i]].state.checked || (m[dpc[i]].original && m[dpc[i]].original.state && m[dpc[i]].original.state.checked); + if(m[dpc[i]].state.checked) { + this._data.checkbox.selected.push(dpc[i]); + } + } + }, this)); + } + if(this.settings.checkbox.cascade.indexOf('up') !== -1 || this.settings.checkbox.cascade.indexOf('down') !== -1) { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + p = m[data.parent], + dpc = data.nodes, + chd = [], + c, i, j, k, l, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection; + + if(s.indexOf('down') !== -1) { + // apply down + if(p.state[ t ? 'selected' : 'checked' ]) { + for(i = 0, j = dpc.length; i < j; i++) { + m[dpc[i]].state[ t ? 'selected' : 'checked' ] = true; + } + this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(dpc); + } + else { + for(i = 0, j = dpc.length; i < j; i++) { + if(m[dpc[i]].state[ t ? 'selected' : 'checked' ]) { + for(k = 0, l = m[dpc[i]].children_d.length; k < l; k++) { + m[m[dpc[i]].children_d[k]].state[ t ? 'selected' : 'checked' ] = true; + } + this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(m[dpc[i]].children_d); + } + } + } + } + + if(s.indexOf('up') !== -1) { + // apply up + for(i = 0, j = p.children_d.length; i < j; i++) { + if(!m[p.children_d[i]].children.length) { + chd.push(m[p.children_d[i]].parent); + } + } + chd = $.vakata.array_unique(chd); + for(k = 0, l = chd.length; k < l; k++) { + p = m[chd[k]]; + while(p && p.id !== $.jstree.root) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass( t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + } + + this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected); + }, this)) + .on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + m = this._model.data, + par = this.get_node(obj.parent), + dom = this.get_node(obj, true), + i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection, + sel = {}, cur = this._data[ t ? 'core' : 'checkbox' ].selected; + + for (i = 0, j = cur.length; i < j; i++) { + sel[cur[i]] = true; + } + // apply down + if(s.indexOf('down') !== -1) { + //this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d)); + for(i = 0, j = obj.children_d.length; i < j; i++) { + sel[obj.children_d[i]] = true; + tmp = m[obj.children_d[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = true; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + } + + // apply up + if(s.indexOf('up') !== -1) { + while(par && par.id !== $.jstree.root) { + c = 0; + for(i = 0, j = par.children.length; i < j; i++) { + c += m[par.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + par.state[ t ? 'selected' : 'checked' ] = true; + sel[par.id] = true; + //this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id); + tmp = this.get_node(par, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + par = this.get_node(par.parent); + } + } + + cur = []; + for (i in sel) { + if (sel.hasOwnProperty(i)) { + cur.push(i); + } + } + this._data[ t ? 'core' : 'checkbox' ].selected = cur; + + // apply down (process .children separately?) + if(s.indexOf('down') !== -1 && dom.length) { + dom.find('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', true); + } + }, this)) + .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) { + var obj = this.get_node($.jstree.root), + m = this._model.data, + i, j, tmp; + for(i = 0, j = obj.children_d.length; i < j; i++) { + tmp = m[obj.children_d[i]]; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + }, this)) + .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + dom = this.get_node(obj, true), + i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection, + cur = this._data[ t ? 'core' : 'checkbox' ].selected, sel = {}; + if(obj && obj.original && obj.original.state && obj.original.state.undetermined) { + obj.original.state.undetermined = false; + } + + // apply down + if(s.indexOf('down') !== -1) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + tmp = this._model.data[obj.children_d[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = false; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + } + } + + // apply up + if(s.indexOf('up') !== -1) { + for(i = 0, j = obj.parents.length; i < j; i++) { + tmp = this._model.data[obj.parents[i]]; + tmp.state[ t ? 'selected' : 'checked' ] = false; + if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) { + tmp.original.state.undetermined = false; + } + tmp = this.get_node(obj.parents[i], true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + } + sel = {}; + for(i = 0, j = cur.length; i < j; i++) { + // apply down + apply up + if( + (s.indexOf('down') === -1 || $.inArray(cur[i], obj.children_d) === -1) && + (s.indexOf('up') === -1 || $.inArray(cur[i], obj.parents) === -1) + ) { + sel[cur[i]] = true; + } + } + cur = []; + for (i in sel) { + if (sel.hasOwnProperty(i)) { + cur.push(i); + } + } + this._data[ t ? 'core' : 'checkbox' ].selected = cur; + + // apply down (process .children separately?) + if(s.indexOf('down') !== -1 && dom.length) { + dom.find('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', false); + } + }, this)); + } + if(this.settings.checkbox.cascade.indexOf('up') !== -1) { + this.element + .on('delete_node.jstree', $.proxy(function (e, data) { + // apply up (whole handler) + var p = this.get_node(data.parent), + m = this._model.data, + i, j, c, tmp, t = this.settings.checkbox.tie_selection; + while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(j > 0 && c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + }, this)) + .on('move_node.jstree', $.proxy(function (e, data) { + // apply up (whole handler) + var is_multi = data.is_multi, + old_par = data.old_parent, + new_par = this.get_node(data.parent), + m = this._model.data, + p, c, i, j, tmp, t = this.settings.checkbox.tie_selection; + if(!is_multi) { + p = this.get_node(old_par); + while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(j > 0 && c === j) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + p = new_par; + while(p && p.id !== $.jstree.root) { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state[ t ? 'selected' : 'checked' ]; + } + if(c === j) { + if(!p.state[ t ? 'selected' : 'checked' ]) { + p.state[ t ? 'selected' : 'checked' ] = true; + this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + } + else { + if(p.state[ t ? 'selected' : 'checked' ]) { + p.state[ t ? 'selected' : 'checked' ] = false; + this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_remove_item(this._data[ t ? 'core' : 'checkbox' ].selected, p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked'); + } + } + else { + break; + } + } + p = this.get_node(p.parent); + } + }, this)); + } + }; + /** + * set the undetermined state where and if necessary. Used internally. + * @private + * @name _undetermined() + * @plugin checkbox + */ + this._undetermined = function () { + if(this.element === null) { return; } + var i, j, k, l, o = {}, m = this._model.data, t = this.settings.checkbox.tie_selection, s = this._data[ t ? 'core' : 'checkbox' ].selected, p = [], tt = this; + for(i = 0, j = s.length; i < j; i++) { + if(m[s[i]] && m[s[i]].parents) { + for(k = 0, l = m[s[i]].parents.length; k < l; k++) { + if(o[m[s[i]].parents[k]] !== undefined) { + break; + } + if(m[s[i]].parents[k] !== $.jstree.root) { + o[m[s[i]].parents[k]] = true; + p.push(m[s[i]].parents[k]); + } + } + } + } + // attempt for server side undetermined state + this.element.find('.jstree-closed').not(':has(.jstree-children)') + .each(function () { + var tmp = tt.get_node(this), tmp2; + if(!tmp.state.loaded) { + if(tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) { + if(o[tmp.id] === undefined && tmp.id !== $.jstree.root) { + o[tmp.id] = true; + p.push(tmp.id); + } + for(k = 0, l = tmp.parents.length; k < l; k++) { + if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) { + o[tmp.parents[k]] = true; + p.push(tmp.parents[k]); + } + } + } + } + else { + for(i = 0, j = tmp.children_d.length; i < j; i++) { + tmp2 = m[tmp.children_d[i]]; + if(!tmp2.state.loaded && tmp2.original && tmp2.original.state && tmp2.original.state.undetermined && tmp2.original.state.undetermined === true) { + if(o[tmp2.id] === undefined && tmp2.id !== $.jstree.root) { + o[tmp2.id] = true; + p.push(tmp2.id); + } + for(k = 0, l = tmp2.parents.length; k < l; k++) { + if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) { + o[tmp2.parents[k]] = true; + p.push(tmp2.parents[k]); + } + } + } + } + } + }); + + this.element.find('.jstree-undetermined').removeClass('jstree-undetermined'); + for(i = 0, j = p.length; i < j; i++) { + if(!m[p[i]].state[ t ? 'selected' : 'checked' ]) { + s = this.get_node(p[i], true); + if(s && s.length) { + s.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-undetermined'); + } + } + } + }; + this.redraw_node = function(obj, deep, is_callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + var i, j, tmp = null, icon = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + if(!this.settings.checkbox.tie_selection && this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; } + icon = _i.cloneNode(false); + if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += ' jstree-checkbox-disabled'; } + tmp.insertBefore(icon, tmp.childNodes[0]); + } + } + if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) { + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + } + return obj; + }; + /** + * show the node checkbox icons + * @name show_checkboxes() + * @plugin checkbox + */ + this.show_checkboxes = function () { this._data.core.themes.checkboxes = true; this.get_container_ul().removeClass("jstree-no-checkboxes"); }; + /** + * hide the node checkbox icons + * @name hide_checkboxes() + * @plugin checkbox + */ + this.hide_checkboxes = function () { this._data.core.themes.checkboxes = false; this.get_container_ul().addClass("jstree-no-checkboxes"); }; + /** + * toggle the node icons + * @name toggle_checkboxes() + * @plugin checkbox + */ + this.toggle_checkboxes = function () { if(this._data.core.themes.checkboxes) { this.hide_checkboxes(); } else { this.show_checkboxes(); } }; + /** + * checks if a node is in an undetermined state + * @name is_undetermined(obj) + * @param {mixed} obj + * @return {Boolean} + */ + this.is_undetermined = function (obj) { + obj = this.get_node(obj); + var s = this.settings.checkbox.cascade, i, j, t = this.settings.checkbox.tie_selection, d = this._data[ t ? 'core' : 'checkbox' ].selected, m = this._model.data; + if(!obj || obj.state[ t ? 'selected' : 'checked' ] === true || s.indexOf('undetermined') === -1 || (s.indexOf('down') === -1 && s.indexOf('up') === -1)) { + return false; + } + if(!obj.state.loaded && obj.original.state.undetermined === true) { + return true; + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + if($.inArray(obj.children_d[i], d) !== -1 || (!m[obj.children_d[i]].state.loaded && m[obj.children_d[i]].original.state.undetermined)) { + return true; + } + } + return false; + }; + /** + * disable a node's checkbox + * @name disable_checkbox(obj) + * @param {mixed} obj an array can be used too + * @trigger disable_checkbox.jstree + * @plugin checkbox + */ + this.disable_checkbox = function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.disable_checkbox(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.checkbox_disabled) { + obj.state.checkbox_disabled = true; + if(dom && dom.length) { + dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled'); + } + /** + * triggered when an node's checkbox is disabled + * @event + * @name disable_checkbox.jstree + * @param {Object} node + * @plugin checkbox + */ + this.trigger('disable_checkbox', { 'node' : obj }); + } + }; + /** + * enable a node's checkbox + * @name disable_checkbox(obj) + * @param {mixed} obj an array can be used too + * @trigger enable_checkbox.jstree + * @plugin checkbox + */ + this.enable_checkbox = function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.enable_checkbox(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.checkbox_disabled) { + obj.state.checkbox_disabled = false; + if(dom && dom.length) { + dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled'); + } + /** + * triggered when an node's checkbox is enabled + * @event + * @name enable_checkbox.jstree + * @param {Object} node + * @plugin checkbox + */ + this.trigger('enable_checkbox', { 'node' : obj }); + } + }; + + this.activate_node = function (obj, e) { + if($(e.target).hasClass('jstree-checkbox-disabled')) { + return false; + } + if(this.settings.checkbox.tie_selection && (this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox'))) { + e.ctrlKey = true; + } + if(this.settings.checkbox.tie_selection || (!this.settings.checkbox.whole_node && !$(e.target).hasClass('jstree-checkbox'))) { + return parent.activate_node.call(this, obj, e); + } + if(this.is_disabled(obj)) { + return false; + } + if(this.is_checked(obj)) { + this.uncheck_node(obj, e); + } + else { + this.check_node(obj, e); + } + this.trigger('activate_node', { 'node' : this.get_node(obj) }); + }; + + /** + * check a node (only if tie_selection in checkbox settings is false, otherwise select_node will be called internally) + * @name check_node(obj) + * @param {mixed} obj an array can be used to check multiple nodes + * @trigger check_node.jstree + * @plugin checkbox + */ + this.check_node = function (obj, e) { + if(this.settings.checkbox.tie_selection) { return this.select_node(obj, false, true, e); } + var dom, t1, t2, th; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.check_node(obj[t1], e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.checked) { + obj.state.checked = true; + this._data.checkbox.selected.push(obj.id); + if(dom && dom.length) { + dom.children('.jstree-anchor').addClass('jstree-checked'); + } + /** + * triggered when an node is checked (only if tie_selection in checkbox settings is false) + * @event + * @name check_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this check_node + * @plugin checkbox + */ + this.trigger('check_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e }); + } + }; + /** + * uncheck a node (only if tie_selection in checkbox settings is false, otherwise deselect_node will be called internally) + * @name uncheck_node(obj) + * @param {mixed} obj an array can be used to uncheck multiple nodes + * @trigger uncheck_node.jstree + * @plugin checkbox + */ + this.uncheck_node = function (obj, e) { + if(this.settings.checkbox.tie_selection) { return this.deselect_node(obj, false, e); } + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.uncheck_node(obj[t1], e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.checked) { + obj.state.checked = false; + this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, obj.id); + if(dom.length) { + dom.children('.jstree-anchor').removeClass('jstree-checked'); + } + /** + * triggered when an node is unchecked (only if tie_selection in checkbox settings is false) + * @event + * @name uncheck_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this uncheck_node + * @plugin checkbox + */ + this.trigger('uncheck_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e }); + } + }; + /** + * checks all nodes in the tree (only if tie_selection in checkbox settings is false, otherwise select_all will be called internally) + * @name check_all() + * @trigger check_all.jstree, changed.jstree + * @plugin checkbox + */ + this.check_all = function () { + if(this.settings.checkbox.tie_selection) { return this.select_all(); } + var tmp = this._data.checkbox.selected.concat([]), i, j; + this._data.checkbox.selected = this._model.data[$.jstree.root].children_d.concat(); + for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) { + if(this._model.data[this._data.checkbox.selected[i]]) { + this._model.data[this._data.checkbox.selected[i]].state.checked = true; + } + } + this.redraw(true); + /** + * triggered when all nodes are checked (only if tie_selection in checkbox settings is false) + * @event + * @name check_all.jstree + * @param {Array} selected the current selection + * @plugin checkbox + */ + this.trigger('check_all', { 'selected' : this._data.checkbox.selected }); + }; + /** + * uncheck all checked nodes (only if tie_selection in checkbox settings is false, otherwise deselect_all will be called internally) + * @name uncheck_all() + * @trigger uncheck_all.jstree + * @plugin checkbox + */ + this.uncheck_all = function () { + if(this.settings.checkbox.tie_selection) { return this.deselect_all(); } + var tmp = this._data.checkbox.selected.concat([]), i, j; + for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) { + if(this._model.data[this._data.checkbox.selected[i]]) { + this._model.data[this._data.checkbox.selected[i]].state.checked = false; + } + } + this._data.checkbox.selected = []; + this.element.find('.jstree-checked').removeClass('jstree-checked'); + /** + * triggered when all nodes are unchecked (only if tie_selection in checkbox settings is false) + * @event + * @name uncheck_all.jstree + * @param {Object} node the previous selection + * @param {Array} selected the current selection + * @plugin checkbox + */ + this.trigger('uncheck_all', { 'selected' : this._data.checkbox.selected, 'node' : tmp }); + }; + /** + * checks if a node is checked (if tie_selection is on in the settings this function will return the same as is_selected) + * @name is_checked(obj) + * @param {mixed} obj + * @return {Boolean} + * @plugin checkbox + */ + this.is_checked = function (obj) { + if(this.settings.checkbox.tie_selection) { return this.is_selected(obj); } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + return obj.state.checked; + }; + /** + * get an array of all checked nodes (if tie_selection is on in the settings this function will return the same as get_selected) + * @name get_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_selected(full); } + return full ? $.map(this._data.checkbox.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.checkbox.selected; + }; + /** + * get an array of all top level checked nodes (ignoring children of checked nodes) (if tie_selection is on in the settings this function will return the same as get_top_selected) + * @name get_top_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_top_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_top_selected(full); } + var tmp = this.get_checked(true), + obj = {}, i, j, k, l; + for(i = 0, j = tmp.length; i < j; i++) { + obj[tmp[i].id] = tmp[i]; + } + for(i = 0, j = tmp.length; i < j; i++) { + for(k = 0, l = tmp[i].children_d.length; k < l; k++) { + if(obj[tmp[i].children_d[k]]) { + delete obj[tmp[i].children_d[k]]; + } + } + } + tmp = []; + for(i in obj) { + if(obj.hasOwnProperty(i)) { + tmp.push(i); + } + } + return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp; + }; + /** + * get an array of all bottom level checked nodes (ignoring selected parents) (if tie_selection is on in the settings this function will return the same as get_bottom_selected) + * @name get_bottom_checked([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + * @plugin checkbox + */ + this.get_bottom_checked = function (full) { + if(this.settings.checkbox.tie_selection) { return this.get_bottom_selected(full); } + var tmp = this.get_checked(true), + obj = [], i, j; + for(i = 0, j = tmp.length; i < j; i++) { + if(!tmp[i].children.length) { + obj.push(tmp[i].id); + } + } + return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj; + }; + this.load_node = function (obj, callback) { + var k, l, i, j, c, tmp; + if(!$.isArray(obj) && !this.settings.checkbox.tie_selection) { + tmp = this.get_node(obj); + if(tmp && tmp.state.loaded) { + for(k = 0, l = tmp.children_d.length; k < l; k++) { + if(this._model.data[tmp.children_d[k]].state.checked) { + c = true; + this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, tmp.children_d[k]); + } + } + } + } + return parent.load_node.apply(this, arguments); + }; + this.get_state = function () { + var state = parent.get_state.apply(this, arguments); + if(this.settings.checkbox.tie_selection) { return state; } + state.checkbox = this._data.checkbox.selected.slice(); + return state; + }; + this.set_state = function (state, callback) { + var res = parent.set_state.apply(this, arguments); + if(res && state.checkbox) { + if(!this.settings.checkbox.tie_selection) { + this.uncheck_all(); + var _this = this; + $.each(state.checkbox, function (i, v) { + _this.check_node(v); + }); + } + delete state.checkbox; + this.set_state(state, callback); + return false; + } + return res; + }; + this.refresh = function (skip_loading, forget_state) { + if(!this.settings.checkbox.tie_selection) { + this._data.checkbox.selected = []; + } + return parent.refresh.apply(this, arguments); + }; + }; + + // include the checkbox plugin by default + // $.jstree.defaults.plugins.push("checkbox"); +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.conditionalselect.js b/civicrm/bower_components/jstree/src/jstree.conditionalselect.js new file mode 100644 index 0000000000000000000000000000000000000000..012562ec10a5282263d5eea6109f0058ddca5bea --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.conditionalselect.js @@ -0,0 +1,38 @@ +/** + * ### Conditionalselect plugin + * + * This plugin allows defining a callback to allow or deny node selection by user input (activate node method). + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.conditionalselect', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.conditionalselect) { return; } + + /** + * a callback (function) which is invoked in the instance's scope and receives two arguments - the node and the event that triggered the `activate_node` call. Returning false prevents working with the node, returning true allows invoking activate_node. Defaults to returning `true`. + * @name $.jstree.defaults.checkbox.visible + * @plugin checkbox + */ + $.jstree.defaults.conditionalselect = function () { return true; }; + $.jstree.plugins.conditionalselect = function (options, parent) { + // own function + this.activate_node = function (obj, e) { + if(this.settings.conditionalselect.call(this, this.get_node(obj), e)) { + parent.activate_node.call(this, obj, e); + } + }; + }; + +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.contextmenu.js b/civicrm/bower_components/jstree/src/jstree.contextmenu.js new file mode 100644 index 0000000000000000000000000000000000000000..00f4517510d985cb9172c9cfbb9fa4cc06aa86bd --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.contextmenu.js @@ -0,0 +1,653 @@ +/** + * ### Contextmenu plugin + * + * Shows a context menu when a node is right-clicked. + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.contextmenu', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.contextmenu) { return; } + + /** + * stores all defaults for the contextmenu plugin + * @name $.jstree.defaults.contextmenu + * @plugin contextmenu + */ + $.jstree.defaults.contextmenu = { + /** + * a boolean indicating if the node should be selected when the context menu is invoked on it. Defaults to `true`. + * @name $.jstree.defaults.contextmenu.select_node + * @plugin contextmenu + */ + select_node : true, + /** + * a boolean indicating if the menu should be shown aligned with the node. Defaults to `true`, otherwise the mouse coordinates are used. + * @name $.jstree.defaults.contextmenu.show_at_node + * @plugin contextmenu + */ + show_at_node : true, + /** + * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too). + * + * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required). Once a menu item is activated the `action` function will be invoked with an object containing the following keys: item - the contextmenu item definition as seen below, reference - the DOM node that was used (the tree node), element - the contextmenu DOM element, position - an object with x/y properties indicating the position of the menu. + * + * * `separator_before` - a boolean indicating if there should be a separator before this item + * * `separator_after` - a boolean indicating if there should be a separator after this item + * * `_disabled` - a boolean indicating if this action should be disabled + * * `label` - a string - the name of the action (could be a function returning a string) + * * `title` - a string - an optional tooltip for the item + * * `action` - a function to be executed if this item is chosen, the function will receive + * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2) + * * `shortcut_label` - shortcut label (like for example `F2` for rename) + * * `submenu` - an object with the same structure as $.jstree.defaults.contextmenu.items which can be used to create a submenu - each key will be rendered as a separate option in a submenu that will appear once the current item is hovered + * + * @name $.jstree.defaults.contextmenu.items + * @plugin contextmenu + */ + items : function (o, cb) { // Could be an object directly + return { + "create" : { + "separator_before" : false, + "separator_after" : true, + "_disabled" : false, //(this.check("create_node", data.reference, {}, "last")), + "label" : "Create", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.create_node(obj, {}, "last", function (new_node) { + setTimeout(function () { inst.edit(new_node); },0); + }); + } + }, + "rename" : { + "separator_before" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Rename", + /*! + "shortcut" : 113, + "shortcut_label" : 'F2', + "icon" : "glyphicon glyphicon-leaf", + */ + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.edit(obj); + } + }, + "remove" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Delete", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.delete_node(inst.get_selected()); + } + else { + inst.delete_node(obj); + } + } + }, + "ccp" : { + "separator_before" : true, + "icon" : false, + "separator_after" : false, + "label" : "Edit", + "action" : false, + "submenu" : { + "cut" : { + "separator_before" : false, + "separator_after" : false, + "label" : "Cut", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.cut(inst.get_top_selected()); + } + else { + inst.cut(obj); + } + } + }, + "copy" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Copy", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.copy(inst.get_top_selected()); + } + else { + inst.copy(obj); + } + } + }, + "paste" : { + "separator_before" : false, + "icon" : false, + "_disabled" : function (data) { + return !$.jstree.reference(data.reference).can_paste(); + }, + "separator_after" : false, + "label" : "Paste", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.paste(obj); + } + } + } + } + }; + } + }; + + $.jstree.plugins.contextmenu = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + var last_ts = 0, cto = null, ex, ey; + this.element + .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) { + if (e.target.tagName.toLowerCase() === 'input') { + return; + } + e.preventDefault(); + last_ts = e.ctrlKey ? +new Date() : 0; + if(data || cto) { + last_ts = (+new Date()) + 10000; + } + if(cto) { + clearTimeout(cto); + } + if(!this.is_loading(e.currentTarget)) { + this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e); + } + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts > 250)) { // work around safari & macOS ctrl+click + $.vakata.context.hide(); + } + last_ts = 0; + }, this)) + .on("touchstart.jstree", ".jstree-anchor", function (e) { + if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) { + return; + } + ex = e.originalEvent.changedTouches[0].clientX; + ey = e.originalEvent.changedTouches[0].clientY; + cto = setTimeout(function () { + $(e.currentTarget).trigger('contextmenu', true); + }, 750); + }) + .on('touchmove.vakata.jstree', function (e) { + if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.originalEvent.changedTouches[0].clientX) > 50 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 50)) { + clearTimeout(cto); + } + }) + .on('touchend.vakata.jstree', function (e) { + if(cto) { + clearTimeout(cto); + } + }); + + /*! + if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) { + var el = null, tm = null; + this.element + .on("touchstart", ".jstree-anchor", function (e) { + el = e.currentTarget; + tm = +new Date(); + $(document).one("touchend", function (e) { + e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset); + e.currentTarget = e.target; + tm = ((+(new Date())) - tm); + if(e.target === el && tm > 600 && tm < 1000) { + e.preventDefault(); + $(el).trigger('contextmenu', e); + } + el = null; + tm = null; + }); + }); + } + */ + $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) { + this._data.contextmenu.visible = false; + $(data.reference).removeClass('jstree-context'); + }, this)); + }; + this.teardown = function () { + if(this._data.contextmenu.visible) { + $.vakata.context.hide(); + } + parent.teardown.call(this); + }; + + /** + * prepare and show the context menu for a node + * @name show_contextmenu(obj [, x, y]) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Object} e the event if available that triggered the contextmenu + * @plugin contextmenu + * @trigger show_contextmenu.jstree + */ + this.show_contextmenu = function (obj, x, y, e) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var s = this.settings.contextmenu, + d = this.get_node(obj, true), + a = d.children(".jstree-anchor"), + o = false, + i = false; + if(s.show_at_node || x === undefined || y === undefined) { + o = a.offset(); + x = o.left; + y = o.top + this._data.core.li_height; + } + if(this.settings.contextmenu.select_node && !this.is_selected(obj)) { + this.activate_node(obj, e); + } + + i = s.items; + if($.isFunction(i)) { + i = i.call(this, obj, $.proxy(function (i) { + this._show_contextmenu(obj, x, y, i); + }, this)); + } + if($.isPlainObject(i)) { + this._show_contextmenu(obj, x, y, i); + } + }; + /** + * show the prepared context menu for a node + * @name _show_contextmenu(obj, x, y, i) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Number} i the object of items to show + * @plugin contextmenu + * @trigger show_contextmenu.jstree + * @private + */ + this._show_contextmenu = function (obj, x, y, i) { + var d = this.get_node(obj, true), + a = d.children(".jstree-anchor"); + $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) { + var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu'; + $(data.element).addClass(cls); + a.addClass('jstree-context'); + }, this)); + this._data.contextmenu.visible = true; + $.vakata.context.show(a, { 'x' : x, 'y' : y }, i); + /** + * triggered when the contextmenu is shown for a node + * @event + * @name show_contextmenu.jstree + * @param {Object} node the node + * @param {Number} x the x-coordinate of the menu relative to the document + * @param {Number} y the y-coordinate of the menu relative to the document + * @plugin contextmenu + */ + this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y }); + }; + }; + + // contextmenu helper + (function ($) { + var right_to_left = false, + vakata_context = { + element : false, + reference : false, + position_x : 0, + position_y : 0, + items : [], + html : "", + is_visible : false + }; + + $.vakata.context = { + settings : { + hide_onmouseleave : 0, + icons : true + }, + _trigger : function (event_name) { + $(document).triggerHandler("context_" + event_name + ".vakata", { + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }); + }, + _execute : function (i) { + i = vakata_context.items[i]; + return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, { + "item" : i, + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }) : false; + }, + _parse : function (o, is_callback) { + if(!o) { return false; } + if(!is_callback) { + vakata_context.html = ""; + vakata_context.items = []; + } + var str = "", + sep = false, + tmp; + + if(is_callback) { str += "<"+"ul>"; } + $.each(o, function (i, val) { + if(!val) { return true; } + vakata_context.items.push(val); + if(!sep && val.separator_before) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + } + sep = false; + str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">"; + str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">"; + if($.vakata.context.settings.icons) { + str += "<"+"i "; + if(val.icon) { + if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; } + else { str += " class='" + val.icon + "' "; } + } + str += "><"+"/i><"+"span class='vakata-contextmenu-sep'> <"+"/span>"; + } + str += ($.isFunction(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' <span class="vakata-contextmenu-shortcut vakata-contextmenu-shortcut-'+val.shortcut+'">'+ (val.shortcut_label || '') +'</span>':'') + "<"+"/a>"; + if(val.submenu) { + tmp = $.vakata.context._parse(val.submenu, true); + if(tmp) { str += tmp; } + } + str += "<"+"/li>"; + if(val.separator_after) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + sep = true; + } + }); + str = str.replace(/<li class\='vakata-context-separator'\><\/li\>$/,""); + if(is_callback) { str += "</ul>"; } + /** + * triggered on the document when the contextmenu is parsed (HTML is built) + * @event + * @plugin contextmenu + * @name context_parse.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); } + return str.length > 10 ? str : false; + }, + _show_submenu : function (o) { + o = $(o); + if(!o.length || !o.children("ul").length) { return; } + var e = o.children("ul"), + xl = o.offset().left, + x = xl + o.outerWidth(), + y = o.offset().top, + w = e.width(), + h = e.height(), + dw = $(window).width() + $(window).scrollLeft(), + dh = $(window).height() + $(window).scrollTop(); + // може да Ñе ÑпеÑти е една проверка - дали нÑма нÑкой от клаÑовете вече нагоре + if(right_to_left) { + o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left"); + } + else { + o[x + w > dw && xl > dw - x ? "addClass" : "removeClass"]("vakata-context-right"); + } + if(y + h + 10 > dh) { + e.css("bottom","-1px"); + } + + //if does not fit - stick it to the side + if (o.hasClass('vakata-context-right')) { + if (xl < w) { + e.css("margin-right", xl - w); + } + } else { + if (dw - x < w) { + e.css("margin-left", dw - x - w); + } + } + + e.show(); + }, + show : function (reference, position, data) { + var o, e, x, y, w, h, dw, dh, cond = true; + if(vakata_context.element && vakata_context.element.length) { + vakata_context.element.width(''); + } + switch(cond) { + case (!position && !reference): + return false; + case (!!position && !!reference): + vakata_context.reference = reference; + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + case (!position && !!reference): + vakata_context.reference = reference; + o = reference.offset(); + vakata_context.position_x = o.left + reference.outerHeight(); + vakata_context.position_y = o.top; + break; + case (!!position && !reference): + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + } + if(!!reference && !data && $(reference).data('vakata_contextmenu')) { + data = $(reference).data('vakata_contextmenu'); + } + if($.vakata.context._parse(data)) { + vakata_context.element.html(vakata_context.html); + } + if(vakata_context.items.length) { + vakata_context.element.appendTo("body"); + e = vakata_context.element; + x = vakata_context.position_x; + y = vakata_context.position_y; + w = e.width(); + h = e.height(); + dw = $(window).width() + $(window).scrollLeft(); + dh = $(window).height() + $(window).scrollTop(); + if(right_to_left) { + x -= (e.outerWidth() - $(reference).outerWidth()); + if(x < $(window).scrollLeft() + 20) { + x = $(window).scrollLeft() + 20; + } + } + if(x + w + 20 > dw) { + x = dw - (w + 20); + } + if(y + h + 20 > dh) { + y = dh - (h + 20); + } + + vakata_context.element + .css({ "left" : x, "top" : y }) + .show() + .find('a').first().focus().parent().addClass("vakata-context-hover"); + vakata_context.is_visible = true; + /** + * triggered on the document when the contextmenu is shown + * @event + * @plugin contextmenu + * @name context_show.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("show"); + } + }, + hide : function () { + if(vakata_context.is_visible) { + vakata_context.element.hide().find("ul").hide().end().find(':focus').blur().end().detach(); + vakata_context.is_visible = false; + /** + * triggered on the document when the contextmenu is hidden + * @event + * @plugin contextmenu + * @name context_hide.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("hide"); + } + } + }; + $(function () { + right_to_left = $("body").css("direction") === "rtl"; + var to = false; + + vakata_context.element = $("<ul class='vakata-context'></ul>"); + vakata_context.element + .on("mouseenter", "li", function (e) { + e.stopImmediatePropagation(); + + if($.contains(this, e.relatedTarget)) { + // премахнато заради delegate mouseleave по-долу + // $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + return; + } + + if(to) { clearTimeout(to); } + vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(); + + $(this) + .siblings().find("ul").hide().end().end() + .parentsUntil(".vakata-context", "li").addBack().addClass("vakata-context-hover"); + $.vakata.context._show_submenu(this); + }) + // теÑтово - дали не натоварва? + .on("mouseleave", "li", function (e) { + if($.contains(this, e.relatedTarget)) { return; } + $(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover"); + }) + .on("mouseleave", function (e) { + $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + if($.vakata.context.settings.hide_onmouseleave) { + to = setTimeout( + (function (t) { + return function () { $.vakata.context.hide(); }; + }(this)), $.vakata.context.settings.hide_onmouseleave); + } + }) + .on("click", "a", function (e) { + e.preventDefault(); + //}) + //.on("mouseup", "a", function (e) { + if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) { + $.vakata.context.hide(); + } + }) + .on('keydown', 'a', function (e) { + var o = null; + switch(e.which) { + case 13: + case 32: + e.type = "click"; + e.preventDefault(); + $(e.currentTarget).trigger(e); + break; + case 37: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 38: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 39: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 40: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 27: + $.vakata.context.hide(); + e.preventDefault(); + break; + default: + //console.log(e.which); + break; + } + }) + .on('keydown', function (e) { + e.preventDefault(); + var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent(); + if(a.parent().not('.vakata-context-disabled')) { + a.click(); + } + }); + + $(document) + .on("mousedown.vakata.jstree", function (e) { + if(vakata_context.is_visible && !$.contains(vakata_context.element[0], e.target)) { + $.vakata.context.hide(); + } + }) + .on("context_show.vakata.jstree", function (e, data) { + vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"); + if(right_to_left) { + vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl"); + } + // also apply a RTL class? + vakata_context.element.find("ul").hide().end(); + }); + }); + }($)); + // $.jstree.defaults.plugins.push("contextmenu"); +})); diff --git a/civicrm/bower_components/jstree/src/jstree.dnd.js b/civicrm/bower_components/jstree/src/jstree.dnd.js new file mode 100644 index 0000000000000000000000000000000000000000..a8a4cec2ec715fd0daab4d2faf8764e5cc160388 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.dnd.js @@ -0,0 +1,653 @@ +/** + * ### Drag'n'drop plugin + * + * Enables dragging and dropping of nodes in the tree, resulting in a move or copy operations. + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.dnd', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.dnd) { return; } + + /** + * stores all defaults for the drag'n'drop plugin + * @name $.jstree.defaults.dnd + * @plugin dnd + */ + $.jstree.defaults.dnd = { + /** + * a boolean indicating if a copy should be possible while dragging (by pressint the meta key or Ctrl). Defaults to `true`. + * @name $.jstree.defaults.dnd.copy + * @plugin dnd + */ + copy : true, + /** + * a number indicating how long a node should remain hovered while dragging to be opened. Defaults to `500`. + * @name $.jstree.defaults.dnd.open_timeout + * @plugin dnd + */ + open_timeout : 500, + /** + * a function invoked each time a node is about to be dragged, invoked in the tree's scope and receives the nodes about to be dragged as an argument (array) and the event that started the drag - return `false` to prevent dragging + * @name $.jstree.defaults.dnd.is_draggable + * @plugin dnd + */ + is_draggable : true, + /** + * a boolean indicating if checks should constantly be made while the user is dragging the node (as opposed to checking only on drop), default is `true` + * @name $.jstree.defaults.dnd.check_while_dragging + * @plugin dnd + */ + check_while_dragging : true, + /** + * a boolean indicating if nodes from this tree should only be copied with dnd (as opposed to moved), default is `false` + * @name $.jstree.defaults.dnd.always_copy + * @plugin dnd + */ + always_copy : false, + /** + * when dropping a node "inside", this setting indicates the position the node should go to - it can be an integer or a string: "first" (same as 0) or "last", default is `0` + * @name $.jstree.defaults.dnd.inside_pos + * @plugin dnd + */ + inside_pos : 0, + /** + * when starting the drag on a node that is selected this setting controls if all selected nodes are dragged or only the single node, default is `true`, which means all selected nodes are dragged when the drag is started on a selected node + * @name $.jstree.defaults.dnd.drag_selection + * @plugin dnd + */ + drag_selection : true, + /** + * controls whether dnd works on touch devices. If left as boolean true dnd will work the same as in desktop browsers, which in some cases may impair scrolling. If set to boolean false dnd will not work on touch devices. There is a special third option - string "selected" which means only selected nodes can be dragged on touch devices. + * @name $.jstree.defaults.dnd.touch + * @plugin dnd + */ + touch : true, + /** + * controls whether items can be dropped anywhere on the node, not just on the anchor, by default only the node anchor is a valid drop target. Works best with the wholerow plugin. If enabled on mobile depending on the interface it might be hard for the user to cancel the drop, since the whole tree container will be a valid drop target. + * @name $.jstree.defaults.dnd.large_drop_target + * @plugin dnd + */ + large_drop_target : false, + /** + * controls whether a drag can be initiated from any part of the node and not just the text/icon part, works best with the wholerow plugin. Keep in mind it can cause problems with tree scrolling on mobile depending on the interface - in that case set the touch option to "selected". + * @name $.jstree.defaults.dnd.large_drag_target + * @plugin dnd + */ + large_drag_target : false, + /** + * controls whether use HTML5 dnd api instead of classical. That will allow better integration of dnd events with other HTML5 controls. + * @reference http://caniuse.com/#feat=dragndrop + * @name $.jstree.defaults.dnd.use_html5 + * @plugin dnd + */ + use_html5: false + }; + var drg, elm; + // TODO: now check works by checking for each node individually, how about max_children, unique, etc? + $.jstree.plugins.dnd = function (options, parent) { + this.init = function (el, options) { + parent.init.call(this, el, options); + this.settings.dnd.use_html5 = this.settings.dnd.use_html5 && ('draggable' in document.createElement('span')); + }; + this.bind = function () { + parent.bind.call(this); + + this.element + .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) { + if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) { + return true; + } + if(e.type === "touchstart" && (!this.settings.dnd.touch || (this.settings.dnd.touch === 'selected' && !$(e.currentTarget).closest('.jstree-node').children('.jstree-anchor').hasClass('jstree-clicked')))) { + return true; + } + var obj = this.get_node(e.target), + mlt = this.is_selected(obj) && this.settings.dnd.drag_selection ? this.get_top_selected().length : 1, + txt = (mlt > 1 ? mlt + ' ' + this.get_string('nodes') : this.get_text(e.currentTarget)); + if(this.settings.core.force_text) { + txt = $.vakata.html.escape(txt); + } + if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") && + (this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e))) + ) { + drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] }; + elm = e.currentTarget; + if (this.settings.dnd.use_html5) { + $.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg }); + } else { + this.element.trigger('mousedown.jstree'); + return $.vakata.dnd.start(e, drg, '<div id="jstree-dnd" class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' + this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' + txt + '<ins class="jstree-copy" style="display:none;">+</ins></div>'); + } + } + }, this)); + if (this.settings.dnd.use_html5) { + this.element + .on('dragover.jstree', function (e) { + e.preventDefault(); + $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg }); + return false; + }) + //.on('dragenter.jstree', this.settings.dnd.large_drop_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) { + // e.preventDefault(); + // $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg }); + // return false; + // }, this)) + .on('drop.jstree', $.proxy(function (e) { + e.preventDefault(); + $.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg }); + return false; + }, this)); + } + }; + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if (obj && this.settings.dnd.use_html5) { + if (this.settings.dnd.large_drag_target) { + obj.setAttribute('draggable', true); + } else { + var i, j, tmp = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + tmp.setAttribute('draggable', true); + } + } + } + return obj; + }; + }; + + $(function() { + // bind only once for all instances + var lastmv = false, + laster = false, + lastev = false, + opento = false, + marker = $('<div id="jstree-marker"> </div>').hide(); //.appendTo('body'); + + $(document) + .on('dnd_start.vakata.jstree', function (e, data) { + lastmv = false; + lastev = false; + if(!data || !data.data || !data.data.jstree) { return; } + marker.appendTo('body'); //.show(); + }) + .on('dnd_move.vakata.jstree', function (e, data) { + if(opento) { + if (!data.event || data.event.type !== 'dragover' || data.event.target !== lastev.target) { + clearTimeout(opento); + } + } + if(!data || !data.data || !data.data.jstree) { return; } + + // if we are hovering the marker image do nothing (can happen on "inside" drags) + if(data.event.target.id && data.event.target.id === 'jstree-marker') { + return; + } + lastev = data.event; + + var ins = $.jstree.reference(data.event.target), + ref = false, + off = false, + rel = false, + tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm, is_copy, pn; + // if we are over an instance + if(ins && ins._data && ins._data.dnd) { + marker.attr('class', 'jstree-' + ins.get_theme() + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' )); + is_copy = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))); + data.helper + .children().attr('class', 'jstree-' + ins.get_theme() + ' jstree-' + ins.get_theme() + '-' + ins.get_theme_variant() + ' ' + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' )) + .find('.jstree-copy').first()[ is_copy ? 'show' : 'hide' ](); + + // if are hovering the container itself add a new root node + //console.log(data.event); + if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) { + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + ok = ok && ins.check( (data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' : ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }); + if(!ok) { break; } + } + if(ok) { + lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' }; + marker.hide(); + data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move'; + } + return; + } + } + else { + // if we are hovering a tree node + ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor'); + if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) { + off = ref.offset(); + rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top; + h = ref.outerHeight(); + if(rel < h / 3) { + o = ['b', 'i', 'a']; + } + else if(rel > h - h / 3) { + o = ['a', 'i', 'b']; + } + else { + o = rel > h / 2 ? ['i', 'a', 'b'] : ['i', 'b', 'a']; + } + $.each(o, function (j, v) { + switch(v) { + case 'b': + l = off.left - 6; + t = off.top; + p = ins.get_parent(ref); + i = ref.parent().index(); + break; + case 'i': + ip = ins.settings.dnd.inside_pos; + tm = ins.get_node(ref.parent()); + l = off.left - 2; + t = off.top + h / 2 + 1; + p = tm.id; + i = ip === 'first' ? 0 : (ip === 'last' ? tm.children.length : Math.min(ip, tm.children.length)); + break; + case 'a': + l = off.left - 6; + t = off.top + h; + p = ins.get_parent(ref); + i = ref.parent().index() + 1; + break; + } + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + op = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? "copy_node" : "move_node"; + ps = i; + if(op === "move_node" && v === 'a' && (data.data.origin && data.data.origin === ins) && p === ins.get_parent(data.data.nodes[t1])) { + pr = ins.get_node(p); + if(ps > $.inArray(data.data.nodes[t1], pr.children)) { + ps -= 1; + } + } + ok = ok && ( (ins && ins.settings && ins.settings.dnd && ins.settings.dnd.check_while_dragging === false) || ins.check(op, (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, { 'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }) ); + if(!ok) { + if(ins && ins.last_error) { laster = ins.last_error(); } + break; + } + } + if(v === 'i' && ref.parent().is('.jstree-closed') && ins.settings.dnd.open_timeout) { + opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout); + } + if(ok) { + pn = ins.get_node(p, true); + if (!pn.hasClass('.jstree-dnd-parent')) { + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + pn.addClass('jstree-dnd-parent'); + } + lastmv = { 'ins' : ins, 'par' : p, 'pos' : v === 'i' && ip === 'last' && i === 0 && !ins.is_loaded(tm) ? 'last' : i }; + marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show(); + data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move'; + } + laster = {}; + o = true; + return false; + } + }); + if(o === true) { return; } + } + } + } + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + lastmv = false; + data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er'); + if (data.event.originalEvent && data.event.originalEvent.dataTransfer) { + data.event.originalEvent.dataTransfer.dropEffect = 'none'; + } + marker.hide(); + }) + .on('dnd_scroll.vakata.jstree', function (e, data) { + if(!data || !data.data || !data.data.jstree) { return; } + marker.hide(); + lastmv = false; + lastev = false; + data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er'); + }) + .on('dnd_stop.vakata.jstree', function (e, data) { + $('.jstree-dnd-parent').removeClass('jstree-dnd-parent'); + if(opento) { clearTimeout(opento); } + if(!data || !data.data || !data.data.jstree) { return; } + marker.hide().detach(); + var i, j, nodes = []; + if(lastmv) { + for(i = 0, j = data.data.nodes.length; i < j; i++) { + nodes[i] = data.data.origin ? data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i]; + } + lastmv.ins[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par, lastmv.pos, false, false, false, data.data.origin); + } + else { + i = $(data.event.target).closest('.jstree'); + if(i.length && laster && laster.error && laster.error === 'check') { + i = i.jstree(true); + if(i) { + i.settings.core.error.call(this, laster); + } + } + } + lastev = false; + lastmv = false; + }) + .on('keyup.jstree keydown.jstree', function (e, data) { + data = $.vakata.dnd._get(); + if(data && data.data && data.data.jstree) { + if (e.type === "keyup" && e.which === 27) { + if (opento) { clearTimeout(opento); } + lastmv = false; + laster = false; + lastev = false; + opento = false; + marker.hide().detach(); + $.vakata.dnd._clean(); + } else { + data.helper.find('.jstree-copy').first()[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey))) ? 'show' : 'hide' ](); + if(lastev) { + lastev.metaKey = e.metaKey; + lastev.ctrlKey = e.ctrlKey; + $.vakata.dnd._trigger('move', lastev); + } + } + } + }); + }); + + // helpers + (function ($) { + $.vakata.html = { + div : $('<div />'), + escape : function (str) { + return $.vakata.html.div.text(str).html(); + }, + strip : function (str) { + return $.vakata.html.div.empty().append($.parseHTML(str)).text(); + } + }; + // private variable + var vakata_dnd = { + element : false, + target : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false, + is_touch: false + }; + $.vakata.dnd = { + settings : { + scroll_speed : 10, + scroll_proximity : 20, + helper_left : 5, + helper_top : 10, + threshold : 5, + threshold_touch : 50 + }, + _trigger : function (event_name, e, data) { + if (data === undefined) { + data = $.vakata.dnd._get(); + } + data.event = e; + $(document).triggerHandler("dnd_" + event_name + ".vakata", data); + }, + _get : function () { + return { + "data" : vakata_dnd.data, + "element" : vakata_dnd.element, + "helper" : vakata_dnd.helper + }; + }, + _clean : function () { + if(vakata_dnd.helper) { vakata_dnd.helper.remove(); } + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + vakata_dnd = { + element : false, + target : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false, + is_touch: false + }; + $(document).off("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag); + $(document).off("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop); + }, + _scroll : function (init_only) { + if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) { + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + return false; + } + if(!vakata_dnd.scroll_i) { + vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100); + return false; + } + if(init_only === true) { return false; } + + var i = vakata_dnd.scroll_e.scrollTop(), + j = vakata_dnd.scroll_e.scrollLeft(); + vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed); + vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed); + if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) { + /** + * triggered on the document when a drag causes an element to scroll + * @event + * @plugin dnd + * @name dnd_scroll.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {jQuery} event the element that is scrolling + */ + $.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e); + } + }, + start : function (e, data, html) { + if(e.type === "touchstart" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); } + try { + e.currentTarget.unselectable = "on"; + e.currentTarget.onselectstart = function() { return false; }; + if(e.currentTarget.style) { + e.currentTarget.style.touchAction = "none"; + e.currentTarget.style.msTouchAction = "none"; + e.currentTarget.style.MozUserSelect = "none"; + } + } catch(ignore) { } + vakata_dnd.init_x = e.pageX; + vakata_dnd.init_y = e.pageY; + vakata_dnd.data = data; + vakata_dnd.is_down = true; + vakata_dnd.element = e.currentTarget; + vakata_dnd.target = e.target; + vakata_dnd.is_touch = e.type === "touchstart"; + if(html !== false) { + vakata_dnd.helper = $("<div id='vakata-dnd'></div>").html(html).css({ + "display" : "block", + "margin" : "0", + "padding" : "0", + "position" : "absolute", + "top" : "-2000px", + "lineHeight" : "16px", + "zIndex" : "10000" + }); + } + $(document).on("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag); + $(document).on("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop); + return false; + }, + drag : function (e) { + if(e.type === "touchmove" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(!vakata_dnd.is_down) { return; } + if(!vakata_dnd.is_drag) { + if( + Math.abs(e.pageX - vakata_dnd.init_x) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) || + Math.abs(e.pageY - vakata_dnd.init_y) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) + ) { + if(vakata_dnd.helper) { + vakata_dnd.helper.appendTo("body"); + vakata_dnd.helper_w = vakata_dnd.helper.outerWidth(); + } + vakata_dnd.is_drag = true; + $(vakata_dnd.target).one('click.vakata', false); + /** + * triggered on the document when a drag starts + * @event + * @plugin dnd + * @name dnd_start.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the start (probably mousemove) + */ + $.vakata.dnd._trigger("start", e); + } + else { return; } + } + + var d = false, w = false, + dh = false, wh = false, + dw = false, ww = false, + dt = false, dl = false, + ht = false, hl = false; + + vakata_dnd.scroll_t = 0; + vakata_dnd.scroll_l = 0; + vakata_dnd.scroll_e = false; + $($(e.target).parentsUntil("body").addBack().get().reverse()) + .filter(function () { + return (/^auto|scroll$/).test($(this).css("overflow")) && + (this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth); + }) + .each(function () { + var t = $(this), o = t.offset(); + if(this.scrollHeight > this.offsetHeight) { + if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + } + if(this.scrollWidth > this.offsetWidth) { + if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = $(this); + return false; + } + }); + + if(!vakata_dnd.scroll_e) { + d = $(document); w = $(window); + dh = d.height(); wh = w.height(); + dw = d.width(); ww = w.width(); + dt = d.scrollTop(); dl = d.scrollLeft(); + if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = d; + } + } + if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); } + + if(vakata_dnd.helper) { + ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10); + hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10); + if(dh && ht + 25 > dh) { ht = dh - 50; } + if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); } + vakata_dnd.helper.css({ + left : hl + "px", + top : ht + "px" + }); + } + /** + * triggered on the document when a drag is in progress + * @event + * @plugin dnd + * @name dnd_move.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused this to trigger (most likely mousemove) + */ + $.vakata.dnd._trigger("move", e); + return false; + }, + stop : function (e) { + if(e.type === "touchend" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { + /** + * triggered on the document when a drag stops (the dragged element is dropped) + * @event + * @plugin dnd + * @name dnd_stop.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the stop + */ + if (e.target !== vakata_dnd.target) { + $(vakata_dnd.target).off('click.vakata'); + } + $.vakata.dnd._trigger("stop", e); + } + else { + if(e.type === "touchend" && e.target === vakata_dnd.target) { + var to = setTimeout(function () { $(e.target).click(); }, 100); + $(e.target).one('click', function() { if(to) { clearTimeout(to); } }); + } + } + $.vakata.dnd._clean(); + return false; + } + }; + }($)); + + // include the dnd plugin by default + // $.jstree.defaults.plugins.push("dnd"); +})); diff --git a/civicrm/bower_components/jstree/src/jstree.js b/civicrm/bower_components/jstree/src/jstree.js new file mode 100644 index 0000000000000000000000000000000000000000..a8677045907e25e4fbbf659b68b2037a9a92d9f7 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.js @@ -0,0 +1,4810 @@ +/*! + * jsTree {{VERSION}} + * http://jstree.com/ + * + * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com) + * + * Licensed same as jquery - under the terms of the MIT License + * http://www.opensource.org/licenses/mit-license.php + */ +/*! + * if using jslint please allow for the jQuery global and use following options: + * jslint: loopfunc: true, browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true + */ +/*jshint -W083 */ +/*globals jQuery, define, module, exports, require, window, document, postMessage */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else if(typeof module !== 'undefined' && module.exports) { + module.exports = factory(require('jquery')); + } + else { + factory(jQuery); + } +}(function ($, undefined) { + "use strict"; + + // prevent another load? maybe there is a better way? + if($.jstree) { + return; + } + + /** + * ### jsTree core functionality + */ + + // internal variables + var instance_counter = 0, + ccp_node = false, + ccp_mode = false, + ccp_inst = false, + themes_loaded = [], + src = $('script:last').attr('src'), + document = window.document; // local variable is always faster to access then a global + + /** + * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances. + * @name $.jstree + */ + $.jstree = { + /** + * specifies the jstree version in use + * @name $.jstree.version + */ + version : '{{VERSION}}', + /** + * holds all the default options used when creating new instances + * @name $.jstree.defaults + */ + defaults : { + /** + * configure which plugins will be active on an instance. Should be an array of strings, where each element is a plugin name. The default is `[]` + * @name $.jstree.defaults.plugins + */ + plugins : [] + }, + /** + * stores all loaded jstree plugins (used internally) + * @name $.jstree.plugins + */ + plugins : {}, + path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '', + idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g, + root : '#' + }; + + /** + * creates a jstree instance + * @name $.jstree.create(el [, options]) + * @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector + * @param {Object} options options for this instance (extends `$.jstree.defaults`) + * @return {jsTree} the new instance + */ + $.jstree.create = function (el, options) { + var tmp = new $.jstree.core(++instance_counter), + opt = options; + options = $.extend(true, {}, $.jstree.defaults, options); + if(opt && opt.plugins) { + options.plugins = opt.plugins; + } + $.each(options.plugins, function (i, k) { + if(i !== 'core') { + tmp = tmp.plugin(k, options[k]); + } + }); + $(el).data('jstree', tmp); + tmp.init(el, options); + return tmp; + }; + /** + * remove all traces of jstree from the DOM and destroy all instances + * @name $.jstree.destroy() + */ + $.jstree.destroy = function () { + $('.jstree:jstree').jstree('destroy'); + $(document).off('.jstree'); + }; + /** + * the jstree class constructor, used only internally + * @private + * @name $.jstree.core(id) + * @param {Number} id this instance's index + */ + $.jstree.core = function (id) { + this._id = id; + this._cnt = 0; + this._wrk = null; + this._data = { + core : { + themes : { + name : false, + dots : false, + icons : false, + ellipsis : false + }, + selected : [], + last_error : {}, + working : false, + worker_queue : [], + focused : null + } + }; + }; + /** + * get a reference to an existing instance + * + * __Examples__ + * + * // provided a container with an ID of "tree", and a nested node with an ID of "branch" + * // all of there will return the same instance + * $.jstree.reference('tree'); + * $.jstree.reference('#tree'); + * $.jstree.reference($('#tree')); + * $.jstree.reference(document.getElementByID('tree')); + * $.jstree.reference('branch'); + * $.jstree.reference('#branch'); + * $.jstree.reference($('#branch')); + * $.jstree.reference(document.getElementByID('branch')); + * + * @name $.jstree.reference(needle) + * @param {DOMElement|jQuery|String} needle + * @return {jsTree|null} the instance or `null` if not found + */ + $.jstree.reference = function (needle) { + var tmp = null, + obj = null; + if(needle && needle.id && (!needle.tagName || !needle.nodeType)) { needle = needle.id; } + + if(!obj || !obj.length) { + try { obj = $(needle); } catch (ignore) { } + } + if(!obj || !obj.length) { + try { obj = $('#' + needle.replace($.jstree.idregex,'\\$&')); } catch (ignore) { } + } + if(obj && obj.length && (obj = obj.closest('.jstree')).length && (obj = obj.data('jstree'))) { + tmp = obj; + } + else { + $('.jstree').each(function () { + var inst = $(this).data('jstree'); + if(inst && inst._model.data[needle]) { + tmp = inst; + return false; + } + }); + } + return tmp; + }; + /** + * Create an instance, get an instance or invoke a command on a instance. + * + * If there is no instance associated with the current node a new one is created and `arg` is used to extend `$.jstree.defaults` for this new instance. There would be no return value (chaining is not broken). + * + * If there is an existing instance and `arg` is a string the command specified by `arg` is executed on the instance, with any additional arguments passed to the function. If the function returns a value it will be returned (chaining could break depending on function). + * + * If there is an existing instance and `arg` is not a string the instance itself is returned (similar to `$.jstree.reference`). + * + * In any other case - nothing is returned and chaining is not broken. + * + * __Examples__ + * + * $('#tree1').jstree(); // creates an instance + * $('#tree2').jstree({ plugins : [] }); // create an instance with some options + * $('#tree1').jstree('open_node', '#branch_1'); // call a method on an existing instance, passing additional arguments + * $('#tree2').jstree(); // get an existing instance (or create an instance) + * $('#tree2').jstree(true); // get an existing instance (will not create new instance) + * $('#branch_1').jstree().select_node('#branch_1'); // get an instance (using a nested element and call a method) + * + * @name $().jstree([arg]) + * @param {String|Object} arg + * @return {Mixed} + */ + $.fn.jstree = function (arg) { + // check for string argument + var is_method = (typeof arg === 'string'), + args = Array.prototype.slice.call(arguments, 1), + result = null; + if(arg === true && !this.length) { return false; } + this.each(function () { + // get the instance (if there is one) and method (if it exists) + var instance = $.jstree.reference(this), + method = is_method && instance ? instance[arg] : null; + // if calling a method, and method is available - execute on the instance + result = is_method && method ? + method.apply(instance, args) : + null; + // if there is no instance and no method is being called - create one + if(!instance && !is_method && (arg === undefined || $.isPlainObject(arg))) { + $.jstree.create(this, arg); + } + // if there is an instance and no method is called - return the instance + if( (instance && !is_method) || arg === true ) { + result = instance || false; + } + // if there was a method call which returned a result - break and return the value + if(result !== null && result !== undefined) { + return false; + } + }); + // if there was a method call with a valid return value - return that, otherwise continue the chain + return result !== null && result !== undefined ? + result : this; + }; + /** + * used to find elements containing an instance + * + * __Examples__ + * + * $('div:jstree').each(function () { + * $(this).jstree('destroy'); + * }); + * + * @name $(':jstree') + * @return {jQuery} + */ + $.expr.pseudos.jstree = $.expr.createPseudo(function(search) { + return function(a) { + return $(a).hasClass('jstree') && + $(a).data('jstree') !== undefined; + }; + }); + + /** + * stores all defaults for the core + * @name $.jstree.defaults.core + */ + $.jstree.defaults.core = { + /** + * data configuration + * + * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items). + * + * You can also pass in a HTML string or a JSON array here. + * + * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree. + * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used. + * + * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result. + * + * __Examples__ + * + * // AJAX + * $('#tree').jstree({ + * 'core' : { + * 'data' : { + * 'url' : '/get/children/', + * 'data' : function (node) { + * return { 'id' : node.id }; + * } + * } + * }); + * + * // direct data + * $('#tree').jstree({ + * 'core' : { + * 'data' : [ + * 'Simple root node', + * { + * 'id' : 'node_2', + * 'text' : 'Root node with options', + * 'state' : { 'opened' : true, 'selected' : true }, + * 'children' : [ { 'text' : 'Child 1' }, 'Child 2'] + * } + * ] + * } + * }); + * + * // function + * $('#tree').jstree({ + * 'core' : { + * 'data' : function (obj, callback) { + * callback.call(this, ['Root 1', 'Root 2']); + * } + * }); + * + * @name $.jstree.defaults.core.data + */ + data : false, + /** + * configure the various strings used throughout the tree + * + * You can use an object where the key is the string you need to replace and the value is your replacement. + * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement. + * If left as `false` no replacement is made. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'strings' : { + * 'Loading ...' : 'Please wait ...' + * } + * } + * }); + * + * @name $.jstree.defaults.core.strings + */ + strings : false, + /** + * determines what happens when a user tries to modify the structure of the tree + * If left as `false` all operations like create, rename, delete, move or copy are prevented. + * You can set this to `true` to allow all interactions or use a function to have better control. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'check_callback' : function (operation, node, node_parent, node_position, more) { + * // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node' + * // in case of 'rename_node' node_position is filled with the new node name + * return operation === 'rename_node' ? true : false; + * } + * } + * }); + * + * @name $.jstree.defaults.core.check_callback + */ + check_callback : false, + /** + * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc) + * @name $.jstree.defaults.core.error + */ + error : $.noop, + /** + * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`) + * @name $.jstree.defaults.core.animation + */ + animation : 200, + /** + * a boolean indicating if multiple nodes can be selected + * @name $.jstree.defaults.core.multiple + */ + multiple : true, + /** + * theme configuration object + * @name $.jstree.defaults.core.themes + */ + themes : { + /** + * the name of the theme to use (if left as `false` the default theme is used) + * @name $.jstree.defaults.core.themes.name + */ + name : false, + /** + * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme. + * @name $.jstree.defaults.core.themes.url + */ + url : false, + /** + * the location of all jstree themes - only used if `url` is set to `true` + * @name $.jstree.defaults.core.themes.dir + */ + dir : false, + /** + * a boolean indicating if connecting dots are shown + * @name $.jstree.defaults.core.themes.dots + */ + dots : true, + /** + * a boolean indicating if node icons are shown + * @name $.jstree.defaults.core.themes.icons + */ + icons : true, + /** + * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container + * @name $.jstree.defaults.core.themes.ellipsis + */ + ellipsis : false, + /** + * a boolean indicating if the tree background is striped + * @name $.jstree.defaults.core.themes.stripes + */ + stripes : false, + /** + * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants) + * @name $.jstree.defaults.core.themes.variant + */ + variant : false, + /** + * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `false`. + * @name $.jstree.defaults.core.themes.responsive + */ + responsive : false + }, + /** + * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user) + * @name $.jstree.defaults.core.expand_selected_onload + */ + expand_selected_onload : true, + /** + * if left as `true` web workers will be used to parse incoming JSON data where possible, so that the UI will not be blocked by large requests. Workers are however about 30% slower. Defaults to `true` + * @name $.jstree.defaults.core.worker + */ + worker : true, + /** + * Force node text to plain text (and escape HTML). Defaults to `false` + * @name $.jstree.defaults.core.force_text + */ + force_text : false, + /** + * Should the node should be toggled if the text is double clicked . Defaults to `true` + * @name $.jstree.defaults.core.dblclick_toggle + */ + dblclick_toggle : true + }; + $.jstree.core.prototype = { + /** + * used to decorate an instance with a plugin. Used internally. + * @private + * @name plugin(deco [, opts]) + * @param {String} deco the plugin to decorate with + * @param {Object} opts options for the plugin + * @return {jsTree} + */ + plugin : function (deco, opts) { + var Child = $.jstree.plugins[deco]; + if(Child) { + this._data[deco] = {}; + Child.prototype = this; + return new Child(opts, this); + } + return this; + }, + /** + * initialize the instance. Used internally. + * @private + * @name init(el, optons) + * @param {DOMElement|jQuery|String} el the element we are transforming + * @param {Object} options options for this instance + * @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree + */ + init : function (el, options) { + this._model = { + data : {}, + changed : [], + force_full_redraw : false, + redraw_timeout : false, + default_state : { + loaded : true, + opened : false, + selected : false, + disabled : false + } + }; + this._model.data[$.jstree.root] = { + id : $.jstree.root, + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + }; + + this.element = $(el).addClass('jstree jstree-' + this._id); + this.settings = options; + + this._data.core.ready = false; + this._data.core.loaded = false; + this._data.core.rtl = (this.element.css("direction") === "rtl"); + this.element[this._data.core.rtl ? 'addClass' : 'removeClass']("jstree-rtl"); + this.element.attr('role','tree'); + if(this.settings.core.multiple) { + this.element.attr('aria-multiselectable', true); + } + if(!this.element.attr('tabindex')) { + this.element.attr('tabindex','0'); + } + + this.bind(); + /** + * triggered after all events are bound + * @event + * @name init.jstree + */ + this.trigger("init"); + + this._data.core.original_container_html = this.element.find(" > ul > li").clone(true); + this._data.core.original_container_html + .find("li").addBack() + .contents().filter(function() { + return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue)); + }) + .remove(); + this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>"); + this.element.attr('aria-activedescendant','j' + this._id + '_loading'); + this._data.core.li_height = this.get_container_ul().children("li").first().height() || 24; + this._data.core.node = this._create_prototype_node(); + /** + * triggered after the loading text is shown and before loading starts + * @event + * @name loading.jstree + */ + this.trigger("loading"); + this.load_node($.jstree.root); + }, + /** + * destroy an instance + * @name destroy() + * @param {Boolean} keep_html if not set to `true` the container will be emptied, otherwise the current DOM elements will be kept intact + */ + destroy : function (keep_html) { + if(this._wrk) { + try { + window.URL.revokeObjectURL(this._wrk); + this._wrk = null; + } + catch (ignore) { } + } + if(!keep_html) { this.element.empty(); } + this.teardown(); + }, + /** + * Create prototype node + */ + _create_prototype_node : function () { + var _node = document.createElement('LI'), _temp1, _temp2; + _node.setAttribute('role', 'treeitem'); + _temp1 = document.createElement('I'); + _temp1.className = 'jstree-icon jstree-ocl'; + _temp1.setAttribute('role', 'presentation'); + _node.appendChild(_temp1); + _temp1 = document.createElement('A'); + _temp1.className = 'jstree-anchor'; + _temp1.setAttribute('href','#'); + _temp1.setAttribute('tabindex','-1'); + _temp2 = document.createElement('I'); + _temp2.className = 'jstree-icon jstree-themeicon'; + _temp2.setAttribute('role', 'presentation'); + _temp1.appendChild(_temp2); + _node.appendChild(_temp1); + _temp1 = _temp2 = null; + + return _node; + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name teardown() + */ + teardown : function () { + this.unbind(); + this.element + .removeClass('jstree') + .removeData('jstree') + .find("[class^='jstree']") + .addBack() + .attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); }); + this.element = null; + }, + /** + * bind all events. Used internally. + * @private + * @name bind() + */ + bind : function () { + var word = '', + tout = null, + was_click = 0; + this.element + .on("dblclick.jstree", function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(document.selection && document.selection.empty) { + document.selection.empty(); + } + else { + if(window.getSelection) { + var sel = window.getSelection(); + try { + sel.removeAllRanges(); + sel.collapse(); + } catch (ignore) { } + } + } + }) + .on("mousedown.jstree", $.proxy(function (e) { + if(e.target === this.element[0]) { + e.preventDefault(); // prevent losing focus when clicking scroll arrows (FF, Chrome) + was_click = +(new Date()); // ie does not allow to prevent losing focus + } + }, this)) + .on("mousedown.jstree", ".jstree-ocl", function (e) { + e.preventDefault(); // prevent any node inside from losing focus when clicking the open/close icon + }) + .on("click.jstree", ".jstree-ocl", $.proxy(function (e) { + this.toggle_node(e.target); + }, this)) + .on("dblclick.jstree", ".jstree-anchor", $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(this.settings.core.dblclick_toggle) { + this.toggle_node(e.target); + } + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + e.preventDefault(); + if(e.currentTarget !== document.activeElement) { $(e.currentTarget).focus(); } + this.activate_node(e.currentTarget, e); + }, this)) + .on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(e.which !== 32 && e.which !== 13 && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) { return true; } + var o = null; + if(this._data.core.rtl) { + if(e.which === 37) { e.which = 39; } + else if(e.which === 39) { e.which = 37; } + } + switch(e.which) { + case 32: // aria defines space only with Ctrl + if(e.ctrlKey) { + e.type = "click"; + $(e.currentTarget).trigger(e); + } + break; + case 13: // enter + e.type = "click"; + $(e.currentTarget).trigger(e); + break; + case 37: // left + e.preventDefault(); + if(this.is_open(e.currentTarget)) { + this.close_node(e.currentTarget); + } + else { + o = this.get_parent(e.currentTarget); + if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); } + } + break; + case 38: // up + e.preventDefault(); + o = this.get_prev_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + case 39: // right + e.preventDefault(); + if(this.is_closed(e.currentTarget)) { + this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); }); + } + else if (this.is_open(e.currentTarget)) { + o = this.get_node(e.currentTarget, true).children('.jstree-children')[0]; + if(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); } + } + break; + case 40: // down + e.preventDefault(); + o = this.get_next_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + case 106: // aria defines * on numpad as open_all - not very common + this.open_all(); + break; + case 36: // home + e.preventDefault(); + o = this._firstChild(this.get_container_ul()[0]); + if(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); } + break; + case 35: // end + e.preventDefault(); + this.element.find('.jstree-anchor').filter(':visible').last().focus(); + break; + case 113: // f2 - safe to include - if check_callback is false it will fail + e.preventDefault(); + this.edit(e.currentTarget); + break; + default: + break; + /*! + // delete + case 46: + e.preventDefault(); + o = this.get_node(e.currentTarget); + if(o && o.id && o.id !== $.jstree.root) { + o = this.is_selected(o) ? this.get_selected() : o; + this.delete_node(o); + } + break; + + */ + } + }, this)) + .on("load_node.jstree", $.proxy(function (e, data) { + if(data.status) { + if(data.node.id === $.jstree.root && !this._data.core.loaded) { + this._data.core.loaded = true; + if(this._firstChild(this.get_container_ul()[0])) { + this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id); + } + /** + * triggered after the root node is loaded for the first time + * @event + * @name loaded.jstree + */ + this.trigger("loaded"); + } + if(!this._data.core.ready) { + setTimeout($.proxy(function() { + if(this.element && !this.get_container_ul().find('.jstree-loading').length) { + this._data.core.ready = true; + if(this._data.core.selected.length) { + if(this.settings.core.expand_selected_onload) { + var tmp = [], i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + tmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents); + } + tmp = $.vakata.array_unique(tmp); + for(i = 0, j = tmp.length; i < j; i++) { + this.open_node(tmp[i], false, 0); + } + } + this.trigger('changed', { 'action' : 'ready', 'selected' : this._data.core.selected }); + } + /** + * triggered after all nodes are finished loading + * @event + * @name ready.jstree + */ + this.trigger("ready"); + } + }, this), 0); + } + } + }, this)) + // quick searching when the tree is focused + .on('keypress.jstree', $.proxy(function (e) { + if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; } + if(tout) { clearTimeout(tout); } + tout = setTimeout(function () { + word = ''; + }, 500); + + var chr = String.fromCharCode(e.which).toLowerCase(), + col = this.element.find('.jstree-anchor').filter(':visible'), + ind = col.index(document.activeElement) || 0, + end = false; + word += chr; + + // match for whole word from current node down (including the current node) + if(word.length > 1) { + col.slice(ind).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().indexOf(word) === 0) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + + // match for whole word from the beginning of the tree + col.slice(0, ind).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().indexOf(word) === 0) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + } + // list nodes that start with that letter (only if word consists of a single char) + if(new RegExp('^' + chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) { + // search for the next node starting with that letter + col.slice(ind + 1).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().charAt(0) === chr) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + + // search from the beginning + col.slice(0, ind + 1).each($.proxy(function (i, v) { + if($(v).text().toLowerCase().charAt(0) === chr) { + $(v).focus(); + end = true; + return false; + } + }, this)); + if(end) { return; } + } + }, this)) + // THEME RELATED + .on("init.jstree", $.proxy(function () { + var s = this.settings.core.themes; + this._data.core.themes.dots = s.dots; + this._data.core.themes.stripes = s.stripes; + this._data.core.themes.icons = s.icons; + this._data.core.themes.ellipsis = s.ellipsis; + this.set_theme(s.name || "default", s.url); + this.set_theme_variant(s.variant); + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ](); + this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ](); + this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ](); + this[ this._data.core.themes.ellipsis ? "show_ellipsis" : "hide_ellipsis" ](); + }, this)) + .on('blur.jstree', '.jstree-anchor', $.proxy(function (e) { + this._data.core.focused = null; + $(e.currentTarget).filter('.jstree-hovered').mouseleave(); + this.element.attr('tabindex', '0'); + }, this)) + .on('focus.jstree', '.jstree-anchor', $.proxy(function (e) { + var tmp = this.get_node(e.currentTarget); + if(tmp && tmp.id) { + this._data.core.focused = tmp.id; + } + this.element.find('.jstree-hovered').not(e.currentTarget).mouseleave(); + $(e.currentTarget).mouseenter(); + this.element.attr('tabindex', '-1'); + }, this)) + .on('focus.jstree', $.proxy(function () { + if(+(new Date()) - was_click > 500 && !this._data.core.focused) { + was_click = 0; + var act = this.get_node(this.element.attr('aria-activedescendant'), true); + if(act) { + act.find('> .jstree-anchor').focus(); + } + } + }, this)) + .on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) { + this.hover_node(e.currentTarget); + }, this)) + .on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name unbind() + */ + unbind : function () { + this.element.off('.jstree'); + $(document).off('.jstree-' + this._id); + }, + /** + * trigger an event. Used internally. + * @private + * @name trigger(ev [, data]) + * @param {String} ev the name of the event to trigger + * @param {Object} data additional data to pass with the event + */ + trigger : function (ev, data) { + if(!data) { + data = {}; + } + data.instance = this; + this.element.triggerHandler(ev.replace('.jstree','') + '.jstree', data); + }, + /** + * returns the jQuery extended instance container + * @name get_container() + * @return {jQuery} + */ + get_container : function () { + return this.element; + }, + /** + * returns the jQuery extended main UL node inside the instance container. Used internally. + * @private + * @name get_container_ul() + * @return {jQuery} + */ + get_container_ul : function () { + return this.element.children(".jstree-children").first(); + }, + /** + * gets string replacements (localization). Used internally. + * @private + * @name get_string(key) + * @param {String} key + * @return {String} + */ + get_string : function (key) { + var a = this.settings.core.strings; + if($.isFunction(a)) { return a.call(this, key); } + if(a && a[key]) { return a[key]; } + return key; + }, + /** + * gets the first child of a DOM node. Used internally. + * @private + * @name _firstChild(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _firstChild : function (dom) { + dom = dom ? dom.firstChild : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the next sibling of a DOM node. Used internally. + * @private + * @name _nextSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _nextSibling : function (dom) { + dom = dom ? dom.nextSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the previous sibling of a DOM node. Used internally. + * @private + * @name _previousSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _previousSibling : function (dom) { + dom = dom ? dom.previousSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.previousSibling; + } + return dom; + }, + /** + * get the JSON representation of a node (or the actual jQuery extended DOM node) by using any input (child DOM element, ID string, selector, etc) + * @name get_node(obj [, as_dom]) + * @param {mixed} obj + * @param {Boolean} as_dom + * @return {Object|jQuery} + */ + get_node : function (obj, as_dom) { + if(obj && obj.id) { + obj = obj.id; + } + var dom; + try { + if(this._model.data[obj]) { + obj = this._model.data[obj]; + } + else if(typeof obj === "string" && this._model.data[obj.replace(/^#/, '')]) { + obj = this._model.data[obj.replace(/^#/, '')]; + } + else if(typeof obj === "string" && (dom = $('#' + obj.replace($.jstree.idregex,'\\$&'), this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) { + obj = this._model.data[dom.closest('.jstree-node').attr('id')]; + } + else if((dom = $(obj, this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) { + obj = this._model.data[dom.closest('.jstree-node').attr('id')]; + } + else if((dom = $(obj, this.element)).length && dom.hasClass('jstree')) { + obj = this._model.data[$.jstree.root]; + } + else { + return false; + } + + if(as_dom) { + obj = obj.id === $.jstree.root ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element); + } + return obj; + } catch (ex) { return false; } + }, + /** + * get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array) + * @name get_path(obj [, glue, ids]) + * @param {mixed} obj the node + * @param {String} glue if you want the path as a string - pass the glue here (for example '/'), if a falsy value is supplied here, an array is returned + * @param {Boolean} ids if set to true build the path using ID, otherwise node text is used + * @return {mixed} + */ + get_path : function (obj, glue, ids) { + obj = obj.parents ? obj : this.get_node(obj); + if(!obj || obj.id === $.jstree.root || !obj.parents) { + return false; + } + var i, j, p = []; + p.push(ids ? obj.id : obj.text); + for(i = 0, j = obj.parents.length; i < j; i++) { + p.push(ids ? obj.parents[i] : this.get_text(obj.parents[i])); + } + p = p.reverse().slice(1); + return glue ? p.join(glue) : p; + }, + /** + * get the next visible node that is below the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_next_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_next_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this._firstChild(this.get_container_ul()[0]); + while (tmp && tmp.offsetHeight === 0) { + tmp = this._nextSibling(tmp); + } + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = obj[0]; + do { + tmp = this._nextSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + return tmp ? $(tmp) : false; + } + if(obj.hasClass("jstree-open")) { + tmp = this._firstChild(obj.children('.jstree-children')[0]); + while (tmp && tmp.offsetHeight === 0) { + tmp = this._nextSibling(tmp); + } + if(tmp !== null) { + return $(tmp); + } + } + tmp = obj[0]; + do { + tmp = this._nextSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + if(tmp !== null) { + return $(tmp); + } + return obj.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first(); + }, + /** + * get the previous visible node that is above the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_prev_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_prev_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this.get_container_ul()[0].lastChild; + while (tmp && tmp.offsetHeight === 0) { + tmp = this._previousSibling(tmp); + } + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = obj[0]; + do { + tmp = this._previousSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + return tmp ? $(tmp) : false; + } + tmp = obj[0]; + do { + tmp = this._previousSibling(tmp); + } while (tmp && tmp.offsetHeight === 0); + if(tmp !== null) { + obj = $(tmp); + while(obj.hasClass("jstree-open")) { + obj = obj.children(".jstree-children").first().children(".jstree-node:visible:last"); + } + return obj; + } + tmp = obj[0].parentNode.parentNode; + return tmp && tmp.className && tmp.className.indexOf('jstree-node') !== -1 ? $(tmp) : false; + }, + /** + * get the parent ID of a node + * @name get_parent(obj) + * @param {mixed} obj + * @return {String} + */ + get_parent : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + return obj.parent; + }, + /** + * get a jQuery collection of all the children of a node (node must be rendered) + * @name get_children_dom(obj) + * @param {mixed} obj + * @return {jQuery} + */ + get_children_dom : function (obj) { + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + return this.get_container_ul().children(".jstree-node"); + } + if(!obj || !obj.length) { + return false; + } + return obj.children(".jstree-children").children(".jstree-node"); + }, + /** + * checks if a node has children + * @name is_parent(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_parent : function (obj) { + obj = this.get_node(obj); + return obj && (obj.state.loaded === false || obj.children.length > 0); + }, + /** + * checks if a node is loaded (its children are available) + * @name is_loaded(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loaded : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.loaded; + }, + /** + * check if a node is currently loading (fetching children) + * @name is_loading(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loading : function (obj) { + obj = this.get_node(obj); + return obj && obj.state && obj.state.loading; + }, + /** + * check if a node is opened + * @name is_open(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_open : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.opened; + }, + /** + * check if a node is in a closed state + * @name is_closed(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_closed : function (obj) { + obj = this.get_node(obj); + return obj && this.is_parent(obj) && !obj.state.opened; + }, + /** + * check if a node has no children + * @name is_leaf(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_leaf : function (obj) { + return !this.is_parent(obj); + }, + /** + * loads a node (fetches its children using the `core.data` setting). Multiple nodes can be passed to by using an array. + * @name load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives two arguments - the node and a boolean status + * @return {Boolean} + * @trigger load_node.jstree + */ + load_node : function (obj, callback) { + var k, l, i, j, c; + if($.isArray(obj)) { + this._load_nodes(obj.slice(), callback); + return true; + } + obj = this.get_node(obj); + if(!obj) { + if(callback) { callback.call(this, obj, false); } + return false; + } + // if(obj.state.loading) { } // the node is already loading - just wait for it to load and invoke callback? but if called implicitly it should be loaded again? + if(obj.state.loaded) { + obj.state.loaded = false; + for(i = 0, j = obj.parents.length; i < j; i++) { + this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) { + return $.inArray(v, obj.children_d) === -1; + }); + } + for(k = 0, l = obj.children_d.length; k < l; k++) { + if(this._model.data[obj.children_d[k]].state.selected) { + c = true; + } + delete this._model.data[obj.children_d[k]]; + } + if (c) { + this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) { + return $.inArray(v, obj.children_d) === -1; + }); + } + obj.children = []; + obj.children_d = []; + if(c) { + this.trigger('changed', { 'action' : 'load_node', 'node' : obj, 'selected' : this._data.core.selected }); + } + } + obj.state.failed = false; + obj.state.loading = true; + this.get_node(obj, true).addClass("jstree-loading").attr('aria-busy',true); + this._load_node(obj, $.proxy(function (status) { + obj = this._model.data[obj.id]; + obj.state.loading = false; + obj.state.loaded = status; + obj.state.failed = !obj.state.loaded; + var dom = this.get_node(obj, true), i = 0, j = 0, m = this._model.data, has_children = false; + for(i = 0, j = obj.children.length; i < j; i++) { + if(m[obj.children[i]] && !m[obj.children[i]].state.hidden) { + has_children = true; + break; + } + } + if(obj.state.loaded && dom && dom.length) { + dom.removeClass('jstree-closed jstree-open jstree-leaf'); + if (!has_children) { + dom.addClass('jstree-leaf'); + } + else { + if (obj.id !== '#') { + dom.addClass(obj.state.opened ? 'jstree-open' : 'jstree-closed'); + } + } + } + dom.removeClass("jstree-loading").attr('aria-busy',false); + /** + * triggered after a node is loaded + * @event + * @name load_node.jstree + * @param {Object} node the node that was loading + * @param {Boolean} status was the node loaded successfully + */ + this.trigger('load_node', { "node" : obj, "status" : status }); + if(callback) { + callback.call(this, obj, status); + } + }, this)); + return true; + }, + /** + * load an array of nodes (will also load unavailable nodes as soon as the appear in the structure). Used internally. + * @private + * @name _load_nodes(nodes [, callback]) + * @param {array} nodes + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - the array passed to _load_nodes + */ + _load_nodes : function (nodes, callback, is_callback, force_reload) { + var r = true, + c = function () { this._load_nodes(nodes, callback, true); }, + m = this._model.data, i, j, tmp = []; + for(i = 0, j = nodes.length; i < j; i++) { + if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || (!is_callback && force_reload) )) { + if(!this.is_loading(nodes[i])) { + this.load_node(nodes[i], c); + } + r = false; + } + } + if(r) { + for(i = 0, j = nodes.length; i < j; i++) { + if(m[nodes[i]] && m[nodes[i]].state.loaded) { + tmp.push(nodes[i]); + } + } + if(callback && !callback.done) { + callback.call(this, tmp); + callback.done = true; + } + } + }, + /** + * loads all unloaded nodes + * @name load_all([obj, callback]) + * @param {mixed} obj the node to load recursively, omit to load all nodes in the tree + * @param {function} callback a function to be executed once loading all the nodes is complete, + * @trigger load_all.jstree + */ + load_all : function (obj, callback) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var to_load = [], + m = this._model.data, + c = m[obj.id].children_d, + i, j; + if(obj.state && !obj.state.loaded) { + to_load.push(obj.id); + } + for(i = 0, j = c.length; i < j; i++) { + if(m[c[i]] && m[c[i]].state && !m[c[i]].state.loaded) { + to_load.push(c[i]); + } + } + if(to_load.length) { + this._load_nodes(to_load, function () { + this.load_all(obj, callback); + }); + } + else { + /** + * triggered after a load_all call completes + * @event + * @name load_all.jstree + * @param {Object} node the recursively loaded node + */ + if(callback) { callback.call(this, obj); } + this.trigger('load_all', { "node" : obj }); + } + }, + /** + * handles the actual loading of a node. Used only internally. + * @private + * @name _load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - a boolean status + * @return {Boolean} + */ + _load_node : function (obj, callback) { + var s = this.settings.core.data, t; + var notTextOrCommentNode = function notTextOrCommentNode () { + return this.nodeType !== 3 && this.nodeType !== 8; + }; + // use original HTML + if(!s) { + if(obj.id === $.jstree.root) { + return this._append_html_data(obj, this._data.core.original_container_html.clone(true), function (status) { + callback.call(this, status); + }); + } + else { + return callback.call(this, false); + } + // return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false); + } + if($.isFunction(s)) { + return s.call(this, obj, $.proxy(function (d) { + if(d === false) { + callback.call(this, false); + } + else { + this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(notTextOrCommentNode) : d, function (status) { + callback.call(this, status); + }); + } + // return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d)); + }, this)); + } + if(typeof s === 'object') { + if(s.url) { + s = $.extend(true, {}, s); + if($.isFunction(s.url)) { + s.url = s.url.call(this, obj); + } + if($.isFunction(s.data)) { + s.data = s.data.call(this, obj); + } + return $.ajax(s) + .done($.proxy(function (d,t,x) { + var type = x.getResponseHeader('Content-Type'); + if((type && type.indexOf('json') !== -1) || typeof d === "object") { + return this._append_json_data(obj, d, function (status) { callback.call(this, status); }); + //return callback.call(this, this._append_json_data(obj, d)); + } + if((type && type.indexOf('html') !== -1) || typeof d === "string") { + return this._append_html_data(obj, $($.parseHTML(d)).filter(notTextOrCommentNode), function (status) { callback.call(this, status); }); + // return callback.call(this, this._append_html_data(obj, $(d))); + } + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + }, this)) + .fail($.proxy(function (f) { + callback.call(this, false); + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)); + } + t = ($.isArray(s) || $.isPlainObject(s)) ? JSON.parse(JSON.stringify(s)) : s; + if(obj.id === $.jstree.root) { + return this._append_json_data(obj, t, function (status) { + callback.call(this, status); + }); + } + else { + this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_05', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + } + //return callback.call(this, (obj.id === $.jstree.root ? this._append_json_data(obj, t) : false) ); + } + if(typeof s === 'string') { + if(obj.id === $.jstree.root) { + return this._append_html_data(obj, $($.parseHTML(s)).filter(notTextOrCommentNode), function (status) { + callback.call(this, status); + }); + } + else { + this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_06', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) }; + this.settings.core.error.call(this, this._data.core.last_error); + return callback.call(this, false); + } + //return callback.call(this, (obj.id === $.jstree.root ? this._append_html_data(obj, $(s)) : false) ); + } + return callback.call(this, false); + }, + /** + * adds a node to the list of nodes to redraw. Used only internally. + * @private + * @name _node_changed(obj [, callback]) + * @param {mixed} obj + */ + _node_changed : function (obj) { + obj = this.get_node(obj); + if(obj) { + this._model.changed.push(obj.id); + } + }, + /** + * appends HTML content to the tree. Used internally. + * @private + * @name _append_html_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the HTML string to parse and append + * @trigger model.jstree, changed.jstree + */ + _append_html_data : function (dom, data, cb) { + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + var dat = data.is('ul') ? data.children() : data, + par = dom.id, + chd = [], + dpc = [], + m = this._model.data, + p = m[par], + s = this._data.core.selected.length, + tmp, i, j; + dat.each($.proxy(function (i, v) { + tmp = this._parse_model_from_html($(v), par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + }, this)); + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + /** + * triggered when new data is inserted to the tree model + * @event + * @name model.jstree + * @param {Array} nodes an array of node IDs + * @param {String} parent the parent ID of the nodes + */ + this.trigger('model', { "nodes" : dpc, 'parent' : par }); + if(par !== $.jstree.root) { + this._node_changed(par); + this.redraw(); + } + else { + this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(this._data.core.selected.length !== s) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + cb.call(this, true); + }, + /** + * appends JSON content to the tree. Used internally. + * @private + * @name _append_json_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the JSON object to parse and append + * @param {Boolean} force_processing internal param - do not set + * @trigger model.jstree, changed.jstree + */ + _append_json_data : function (dom, data, cb, force_processing) { + if(this.element === null) { return; } + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + // *%$@!!! + if(data.d) { + data = data.d; + if(typeof data === "string") { + data = JSON.parse(data); + } + } + if(!$.isArray(data)) { data = [data]; } + var w = null, + args = { + 'df' : this._model.default_state, + 'dat' : data, + 'par' : dom.id, + 'm' : this._model.data, + 't_id' : this._id, + 't_cnt' : this._cnt, + 'sel' : this._data.core.selected + }, + func = function (data, undefined) { + if(data.data) { data = data.data; } + var dat = data.dat, + par = data.par, + chd = [], + dpc = [], + add = [], + df = data.df, + t_id = data.t_id, + t_cnt = data.t_cnt, + m = data.m, + p = m[par], + sel = data.sel, + tmp, i, j, rslt, + parse_flat = function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = d.id.toString(), + i, j, c, e, + tmp = { + id : tid, + text : d.text || '', + icon : d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : d.children || [], + children_d : d.children_d || [], + data : d.data, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tid; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + m[tmp.id] = tmp; + for(i = 0, j = tmp.children.length; i < j; i++) { + c = parse_flat(m[tmp.children[i]], tmp.id, ps); + e = m[c]; + tmp.children_d.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + delete d.data; + delete d.children; + m[tmp.id].original = d; + if(tmp.state.selected) { + add.push(tmp.id); + } + return tmp.id; + }, + parse_nest = function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = false, i, j, c, e, tmp; + do { + tid = 'j' + t_id + '_' + (++t_cnt); + } while(m[tid]); + + tmp = { + id : false, + text : typeof d === 'string' ? d : '', + icon : typeof d === 'object' && d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.id) { tmp.id = d.id.toString(); } + if(d && d.text) { tmp.text = d.text; } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(tmp.li_attr.id && !tmp.id) { + tmp.id = tmp.li_attr.id.toString(); + } + if(!tmp.id) { + tmp.id = tid; + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tmp.id; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children.length) { + for(i = 0, j = d.children.length; i < j; i++) { + c = parse_nest(d.children[i], tmp.id, ps); + e = m[c]; + tmp.children.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + tmp.children_d = tmp.children_d.concat(tmp.children); + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + delete d.data; + delete d.children; + tmp.original = d; + m[tmp.id] = tmp; + if(tmp.state.selected) { + add.push(tmp.id); + } + return tmp.id; + }; + + if(dat.length && dat[0].id !== undefined && dat[0].parent !== undefined) { + // Flat JSON support (for easy import from DB): + // 1) convert to object (foreach) + for(i = 0, j = dat.length; i < j; i++) { + if(!dat[i].children) { + dat[i].children = []; + } + m[dat[i].id.toString()] = dat[i]; + } + // 2) populate children (foreach) + for(i = 0, j = dat.length; i < j; i++) { + m[dat[i].parent.toString()].children.push(dat[i].id.toString()); + // populate parent.children_d + p.children_d.push(dat[i].id.toString()); + } + // 3) normalize && populate parents and children_d with recursion + for(i = 0, j = p.children.length; i < j; i++) { + tmp = parse_flat(m[p.children[i]], par, p.parents.concat()); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + // ?) three_state selection - p.state.selected && t - (if three_state foreach(dat => ch) -> foreach(parents) if(parent.selected) child.selected = true; + rslt = { + 'cnt' : t_cnt, + 'mod' : m, + 'sel' : sel, + 'par' : par, + 'dpc' : dpc, + 'add' : add + }; + } + else { + for(i = 0, j = dat.length; i < j; i++) { + tmp = parse_nest(dat[i], par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + } + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + rslt = { + 'cnt' : t_cnt, + 'mod' : m, + 'sel' : sel, + 'par' : par, + 'dpc' : dpc, + 'add' : add + }; + } + if(typeof window === 'undefined' || typeof window.document === 'undefined') { + postMessage(rslt); + } + else { + return rslt; + } + }, + rslt = function (rslt, worker) { + if(this.element === null) { return; } + this._cnt = rslt.cnt; + var i, m = this._model.data; + for (i in m) { + if (m.hasOwnProperty(i) && m[i].state && m[i].state.loading && rslt.mod[i]) { + rslt.mod[i].state.loading = true; + } + } + this._model.data = rslt.mod; // breaks the reference in load_node - careful + + if(worker) { + var j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice(); + m = this._model.data; + // if selection was changed while calculating in worker + if(r.length !== s.length || $.vakata.array_unique(r.concat(s)).length !== r.length) { + // deselect nodes that are no longer selected + for(i = 0, j = r.length; i < j; i++) { + if($.inArray(r[i], a) === -1 && $.inArray(r[i], s) === -1) { + m[r[i]].state.selected = false; + } + } + // select nodes that were selected in the mean time + for(i = 0, j = s.length; i < j; i++) { + if($.inArray(s[i], r) === -1) { + m[s[i]].state.selected = true; + } + } + } + } + if(rslt.add.length) { + this._data.core.selected = this._data.core.selected.concat(rslt.add); + } + + this.trigger('model', { "nodes" : rslt.dpc, 'parent' : rslt.par }); + + if(rslt.par !== $.jstree.root) { + this._node_changed(rslt.par); + this.redraw(); + } + else { + // this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(rslt.add.length) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + cb.call(this, true); + }; + if(this.settings.core.worker && window.Blob && window.URL && window.Worker) { + try { + if(this._wrk === null) { + this._wrk = window.URL.createObjectURL( + new window.Blob( + ['self.onmessage = ' + func.toString()], + {type:"text/javascript"} + ) + ); + } + if(!this._data.core.working || force_processing) { + this._data.core.working = true; + w = new window.Worker(this._wrk); + w.onmessage = $.proxy(function (e) { + rslt.call(this, e.data, true); + try { w.terminate(); w = null; } catch(ignore) { } + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + }, this); + if(!args.par) { + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + } + else { + w.postMessage(args); + } + } + else { + this._data.core.worker_queue.push([dom, data, cb, true]); + } + } + catch(e) { + rslt.call(this, func(args), false); + if(this._data.core.worker_queue.length) { + this._append_json_data.apply(this, this._data.core.worker_queue.shift()); + } + else { + this._data.core.working = false; + } + } + } + else { + rslt.call(this, func(args), false); + } + }, + /** + * parses a node from a jQuery object and appends them to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_html(d [, p, ps]) + * @param {jQuery} d the jQuery object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_html : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = [].concat(ps); } + if(p) { ps.unshift(p); } + var c, e, m = this._model.data, + data = { + id : false, + text : false, + icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }, i, tmp, tid; + for(i in this._model.default_state) { + if(this._model.default_state.hasOwnProperty(i)) { + data.state[i] = this._model.default_state[i]; + } + } + tmp = $.vakata.attributes(d, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(!v.length) { return true; } + data.li_attr[i] = v; + if(i === 'id') { + data.id = v.toString(); + } + }); + tmp = d.children('a').first(); + if(tmp.length) { + tmp = $.vakata.attributes(tmp, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(v.length) { + data.a_attr[i] = v; + } + }); + } + tmp = d.children("a").first().length ? d.children("a").first().clone() : d.clone(); + tmp.children("ins, i, ul").remove(); + tmp = tmp.html(); + tmp = $('<div />').html(tmp); + data.text = this.settings.core.force_text ? tmp.text() : tmp.html(); + tmp = d.data(); + data.data = tmp ? $.extend(true, {}, tmp) : null; + data.state.opened = d.hasClass('jstree-open'); + data.state.selected = d.children('a').hasClass('jstree-clicked'); + data.state.disabled = d.children('a').hasClass('jstree-disabled'); + if(data.data && data.data.jstree) { + for(i in data.data.jstree) { + if(data.data.jstree.hasOwnProperty(i)) { + data.state[i] = data.data.jstree[i]; + } + } + } + tmp = d.children("a").children(".jstree-themeicon"); + if(tmp.length) { + data.icon = tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel'); + } + if(data.state.icon !== undefined) { + data.icon = data.state.icon; + } + if(data.icon === undefined || data.icon === null || data.icon === "") { + data.icon = true; + } + tmp = d.children("ul").children("li"); + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + data.id = data.li_attr.id ? data.li_attr.id.toString() : tid; + if(tmp.length) { + tmp.each($.proxy(function (i, v) { + c = this._parse_model_from_html($(v), data.id, ps); + e = this._model.data[c]; + data.children.push(c); + if(e.children_d.length) { + data.children_d = data.children_d.concat(e.children_d); + } + }, this)); + data.children_d = data.children_d.concat(data.children); + } + else { + if(d.hasClass('jstree-closed')) { + data.state.loaded = false; + } + } + if(data.li_attr['class']) { + data.li_attr['class'] = data.li_attr['class'].replace('jstree-closed','').replace('jstree-open',''); + } + if(data.a_attr['class']) { + data.a_attr['class'] = data.a_attr['class'].replace('jstree-clicked','').replace('jstree-disabled',''); + } + m[data.id] = data; + if(data.state.selected) { + this._data.core.selected.push(data.id); + } + return data.id; + }, + /** + * parses a node from a JSON object (used when dealing with flat data, which has no nesting of children, but has id and parent properties) and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_flat_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_flat_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = d.id.toString(), + m = this._model.data, + df = this._model.default_state, + i, j, c, e, + tmp = { + id : tid, + text : d.text || '', + icon : d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : d.children || [], + children_d : d.children_d || [], + data : d.data, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tid; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + m[tmp.id] = tmp; + for(i = 0, j = tmp.children.length; i < j; i++) { + c = this._parse_model_from_flat_json(m[tmp.children[i]], tmp.id, ps); + e = m[c]; + tmp.children_d.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + delete d.data; + delete d.children; + m[tmp.id].original = d; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * parses a node from a JSON object and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = false, i, j, c, e, m = this._model.data, df = this._model.default_state, tmp; + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + + tmp = { + id : false, + text : typeof d === 'string' ? d : '', + icon : typeof d === 'object' && d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.id) { tmp.id = d.id.toString(); } + if(d && d.text) { tmp.text = d.text; } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(tmp.icon === undefined || tmp.icon === null || tmp.icon === "") { + tmp.icon = true; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(tmp.li_attr.id && !tmp.id) { + tmp.id = tmp.li_attr.id.toString(); + } + if(!tmp.id) { + tmp.id = tid; + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tmp.id; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children.length) { + for(i = 0, j = d.children.length; i < j; i++) { + c = this._parse_model_from_json(d.children[i], tmp.id, ps); + e = m[c]; + tmp.children.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + tmp.children_d = tmp.children_d.concat(tmp.children); + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + delete d.data; + delete d.children; + tmp.original = d; + m[tmp.id] = tmp; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * redraws all nodes that need to be redrawn. Used internally. + * @private + * @name _redraw() + * @trigger redraw.jstree + */ + _redraw : function () { + var nodes = this._model.force_full_redraw ? this._model.data[$.jstree.root].children.concat([]) : this._model.changed.concat([]), + f = document.createElement('UL'), tmp, i, j, fe = this._data.core.focused; + for(i = 0, j = nodes.length; i < j; i++) { + tmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw); + if(tmp && this._model.force_full_redraw) { + f.appendChild(tmp); + } + } + if(this._model.force_full_redraw) { + f.className = this.get_container_ul()[0].className; + f.setAttribute('role','group'); + this.element.empty().append(f); + //this.get_container_ul()[0].appendChild(f); + } + if(fe !== null) { + tmp = this.get_node(fe, true); + if(tmp && tmp.length && tmp.children('.jstree-anchor')[0] !== document.activeElement) { + tmp.children('.jstree-anchor').focus(); + } + else { + this._data.core.focused = null; + } + } + this._model.force_full_redraw = false; + this._model.changed = []; + /** + * triggered after nodes are redrawn + * @event + * @name redraw.jstree + * @param {array} nodes the redrawn nodes + */ + this.trigger('redraw', { "nodes" : nodes }); + }, + /** + * redraws all nodes that need to be redrawn or optionally - the whole tree + * @name redraw([full]) + * @param {Boolean} full if set to `true` all nodes are redrawn. + */ + redraw : function (full) { + if(full) { + this._model.force_full_redraw = true; + } + //if(this._model.redraw_timeout) { + // clearTimeout(this._model.redraw_timeout); + //} + //this._model.redraw_timeout = setTimeout($.proxy(this._redraw, this),0); + this._redraw(); + }, + /** + * redraws a single node's children. Used internally. + * @private + * @name draw_children(node) + * @param {mixed} node the node whose children will be redrawn + */ + draw_children : function (node) { + var obj = this.get_node(node), + i = false, + j = false, + k = false, + d = document; + if(!obj) { return false; } + if(obj.id === $.jstree.root) { return this.redraw(true); } + node = this.get_node(node, true); + if(!node || !node.length) { return false; } // TODO: quick toggle + + node.children('.jstree-children').remove(); + node = node[0]; + if(obj.children.length && obj.state.loaded) { + k = d.createElement('UL'); + k.setAttribute('role', 'group'); + k.className = 'jstree-children'; + for(i = 0, j = obj.children.length; i < j; i++) { + k.appendChild(this.redraw_node(obj.children[i], true, true)); + } + node.appendChild(k); + } + }, + /** + * redraws a single node. Used internally. + * @private + * @name redraw_node(node, deep, is_callback, force_render) + * @param {mixed} node the node to redraw + * @param {Boolean} deep should child nodes be redrawn too + * @param {Boolean} is_callback is this a recursion call + * @param {Boolean} force_render should children of closed parents be drawn anyway + */ + redraw_node : function (node, deep, is_callback, force_render) { + var obj = this.get_node(node), + par = false, + ind = false, + old = false, + i = false, + j = false, + k = false, + c = '', + d = document, + m = this._model.data, + f = false, + s = false, + tmp = null, + t = 0, + l = 0, + has_children = false, + last_sibling = false; + if(!obj) { return false; } + if(obj.id === $.jstree.root) { return this.redraw(true); } + deep = deep || obj.children.length === 0; + node = !document.querySelector ? document.getElementById(obj.id) : this.element[0].querySelector('#' + ("0123456789".indexOf(obj.id[0]) !== -1 ? '\\3' + obj.id[0] + ' ' + obj.id.substr(1).replace($.jstree.idregex,'\\$&') : obj.id.replace($.jstree.idregex,'\\$&')) ); //, this.element); + if(!node) { + deep = true; + //node = d.createElement('LI'); + if(!is_callback) { + par = obj.parent !== $.jstree.root ? $('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null; + if(par !== null && (!par || !m[obj.parent].state.opened)) { + return false; + } + ind = $.inArray(obj.id, par === null ? m[$.jstree.root].children : m[obj.parent].children); + } + } + else { + node = $(node); + if(!is_callback) { + par = node.parent().parent()[0]; + if(par === this.element[0]) { + par = null; + } + ind = node.index(); + } + // m[obj.id].data = node.data(); // use only node's data, no need to touch jquery storage + if(!deep && obj.children.length && !node.children('.jstree-children').length) { + deep = true; + } + if(!deep) { + old = node.children('.jstree-children')[0]; + } + f = node.children('.jstree-anchor')[0] === document.activeElement; + node.remove(); + //node = d.createElement('LI'); + //node = node[0]; + } + node = this._data.core.node.cloneNode(true); + // node is DOM, deep is boolean + + c = 'jstree-node '; + for(i in obj.li_attr) { + if(obj.li_attr.hasOwnProperty(i)) { + if(i === 'id') { continue; } + if(i !== 'class') { + node.setAttribute(i, obj.li_attr[i]); + } + else { + c += obj.li_attr[i]; + } + } + } + if(!obj.a_attr.id) { + obj.a_attr.id = obj.id + '_anchor'; + } + node.setAttribute('aria-selected', !!obj.state.selected); + node.setAttribute('aria-level', obj.parents.length); + node.setAttribute('aria-labelledby', obj.a_attr.id); + if(obj.state.disabled) { + node.setAttribute('aria-disabled', true); + } + + for(i = 0, j = obj.children.length; i < j; i++) { + if(!m[obj.children[i]].state.hidden) { + has_children = true; + break; + } + } + if(obj.parent !== null && m[obj.parent] && !obj.state.hidden) { + i = $.inArray(obj.id, m[obj.parent].children); + last_sibling = obj.id; + if(i !== -1) { + i++; + for(j = m[obj.parent].children.length; i < j; i++) { + if(!m[m[obj.parent].children[i]].state.hidden) { + last_sibling = m[obj.parent].children[i]; + } + if(last_sibling !== obj.id) { + break; + } + } + } + } + + if(obj.state.hidden) { + c += ' jstree-hidden'; + } + if(obj.state.loaded && !has_children) { + c += ' jstree-leaf'; + } + else { + c += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed'; + node.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) ); + } + if(last_sibling === obj.id) { + c += ' jstree-last'; + } + node.id = obj.id; + node.className = c; + c = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : ''); + for(j in obj.a_attr) { + if(obj.a_attr.hasOwnProperty(j)) { + if(j === 'href' && obj.a_attr[j] === '#') { continue; } + if(j !== 'class') { + node.childNodes[1].setAttribute(j, obj.a_attr[j]); + } + else { + c += ' ' + obj.a_attr[j]; + } + } + } + if(c.length) { + node.childNodes[1].className = 'jstree-anchor ' + c; + } + if((obj.icon && obj.icon !== true) || obj.icon === false) { + if(obj.icon === false) { + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-hidden'; + } + else if(obj.icon.indexOf('/') === -1 && obj.icon.indexOf('.') === -1) { + node.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom'; + } + else { + node.childNodes[1].childNodes[0].style.backgroundImage = 'url("'+obj.icon+'")'; + node.childNodes[1].childNodes[0].style.backgroundPosition = 'center center'; + node.childNodes[1].childNodes[0].style.backgroundSize = 'auto'; + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom'; + } + } + + if(this.settings.core.force_text) { + node.childNodes[1].appendChild(d.createTextNode(obj.text)); + } + else { + node.childNodes[1].innerHTML += obj.text; + } + + + if(deep && obj.children.length && (obj.state.opened || force_render) && obj.state.loaded) { + k = d.createElement('UL'); + k.setAttribute('role', 'group'); + k.className = 'jstree-children'; + for(i = 0, j = obj.children.length; i < j; i++) { + k.appendChild(this.redraw_node(obj.children[i], deep, true)); + } + node.appendChild(k); + } + if(old) { + node.appendChild(old); + } + if(!is_callback) { + // append back using par / ind + if(!par) { + par = this.element[0]; + } + for(i = 0, j = par.childNodes.length; i < j; i++) { + if(par.childNodes[i] && par.childNodes[i].className && par.childNodes[i].className.indexOf('jstree-children') !== -1) { + tmp = par.childNodes[i]; + break; + } + } + if(!tmp) { + tmp = d.createElement('UL'); + tmp.setAttribute('role', 'group'); + tmp.className = 'jstree-children'; + par.appendChild(tmp); + } + par = tmp; + + if(ind < par.childNodes.length) { + par.insertBefore(node, par.childNodes[ind]); + } + else { + par.appendChild(node); + } + if(f) { + t = this.element[0].scrollTop; + l = this.element[0].scrollLeft; + node.childNodes[1].focus(); + this.element[0].scrollTop = t; + this.element[0].scrollLeft = l; + } + } + if(obj.state.opened && !obj.state.loaded) { + obj.state.opened = false; + setTimeout($.proxy(function () { + this.open_node(obj.id, false, 0); + }, this), 0); + } + return node; + }, + /** + * opens a node, revaling its children. If the node is not loaded it will be loaded and opened once ready. + * @name open_node(obj [, callback, animation]) + * @param {mixed} obj the node to open + * @param {Function} callback a function to execute once the node is opened + * @param {Number} animation the animation duration in milliseconds when opening the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger open_node.jstree, after_open.jstree, before_open.jstree + */ + open_node : function (obj, callback, animation) { + var t1, t2, d, t; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.open_node(obj[t1], callback, animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + if(!this.is_closed(obj)) { + if(callback) { + callback.call(this, obj, false); + } + return false; + } + if(!this.is_loaded(obj)) { + if(this.is_loading(obj)) { + return setTimeout($.proxy(function () { + this.open_node(obj, callback, animation); + }, this), 500); + } + this.load_node(obj, function (o, ok) { + return ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false); + }); + } + else { + d = this.get_node(obj, true); + t = this; + if(d.length) { + if(animation && d.children(".jstree-children").length) { + d.children(".jstree-children").stop(true, true); + } + if(obj.children.length && !this._firstChild(d.children('.jstree-children')[0])) { + this.draw_children(obj); + //d = this.get_node(obj, true); + } + if(!animation) { + this.trigger('before_open', { "node" : obj }); + d[0].className = d[0].className.replace('jstree-closed', 'jstree-open'); + d[0].setAttribute("aria-expanded", true); + } + else { + this.trigger('before_open', { "node" : obj }); + d + .children(".jstree-children").css("display","none").end() + .removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded", true) + .children(".jstree-children").stop(true, true) + .slideDown(animation, function () { + this.style.display = ""; + if (t.element) { + t.trigger("after_open", { "node" : obj }); + } + }); + } + } + obj.state.opened = true; + if(callback) { + callback.call(this, obj, true); + } + if(!d.length) { + /** + * triggered when a node is about to be opened (if the node is supposed to be in the DOM, it will be, but it won't be visible yet) + * @event + * @name before_open.jstree + * @param {Object} node the opened node + */ + this.trigger('before_open', { "node" : obj }); + } + /** + * triggered when a node is opened (if there is an animation it will not be completed yet) + * @event + * @name open_node.jstree + * @param {Object} node the opened node + */ + this.trigger('open_node', { "node" : obj }); + if(!animation || !d.length) { + /** + * triggered when a node is opened and the animation is complete + * @event + * @name after_open.jstree + * @param {Object} node the opened node + */ + this.trigger("after_open", { "node" : obj }); + } + return true; + } + }, + /** + * opens every parent of a node (node should be loaded) + * @name _open_to(obj) + * @param {mixed} obj the node to reveal + * @private + */ + _open_to : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + var i, j, p = obj.parents; + for(i = 0, j = p.length; i < j; i+=1) { + if(i !== $.jstree.root) { + this.open_node(p[i], false, 0); + } + } + return $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element); + }, + /** + * closes a node, hiding its children + * @name close_node(obj [, animation]) + * @param {mixed} obj the node to close + * @param {Number} animation the animation duration in milliseconds when closing the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger close_node.jstree, after_close.jstree + */ + close_node : function (obj, animation) { + var t1, t2, t, d; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.close_node(obj[t1], animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(this.is_closed(obj)) { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + t = this; + d = this.get_node(obj, true); + + obj.state.opened = false; + /** + * triggered when a node is closed (if there is an animation it will not be complete yet) + * @event + * @name close_node.jstree + * @param {Object} node the closed node + */ + this.trigger('close_node',{ "node" : obj }); + if(!d.length) { + /** + * triggered when a node is closed and the animation is complete + * @event + * @name after_close.jstree + * @param {Object} node the closed node + */ + this.trigger("after_close", { "node" : obj }); + } + else { + if(!animation) { + d[0].className = d[0].className.replace('jstree-open', 'jstree-closed'); + d.attr("aria-expanded", false).children('.jstree-children').remove(); + this.trigger("after_close", { "node" : obj }); + } + else { + d + .children(".jstree-children").attr("style","display:block !important").end() + .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false) + .children(".jstree-children").stop(true, true).slideUp(animation, function () { + this.style.display = ""; + d.children('.jstree-children').remove(); + if (t.element) { + t.trigger("after_close", { "node" : obj }); + } + }); + } + } + }, + /** + * toggles a node - closing it if it is open, opening it if it is closed + * @name toggle_node(obj) + * @param {mixed} obj the node to toggle + */ + toggle_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.toggle_node(obj[t1]); + } + return true; + } + if(this.is_closed(obj)) { + return this.open_node(obj); + } + if(this.is_open(obj)) { + return this.close_node(obj); + } + }, + /** + * opens all nodes within a node (or the tree), revaling their children. If the node is not loaded it will be loaded and opened once ready. + * @name open_all([obj, animation, original_obj]) + * @param {mixed} obj the node to open recursively, omit to open all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation + * @param {jQuery} reference to the node that started the process (internal use) + * @trigger open_all.jstree + */ + open_all : function (obj, animation, original_obj) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), i, j, _this; + if(!dom.length) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + if(this.is_closed(this._model.data[obj.children_d[i]])) { + this._model.data[obj.children_d[i]].state.opened = true; + } + } + return this.trigger('open_all', { "node" : obj }); + } + original_obj = original_obj || dom; + _this = this; + dom = this.is_closed(obj) ? dom.find('.jstree-closed').addBack() : dom.find('.jstree-closed'); + dom.each(function () { + _this.open_node( + this, + function(node, status) { if(status && this.is_parent(node)) { this.open_all(node, animation, original_obj); } }, + animation || 0 + ); + }); + if(original_obj.find('.jstree-closed').length === 0) { + /** + * triggered when an `open_all` call completes + * @event + * @name open_all.jstree + * @param {Object} node the opened node + */ + this.trigger('open_all', { "node" : this.get_node(original_obj) }); + } + }, + /** + * closes all nodes within a node (or the tree), revaling their children + * @name close_all([obj, animation]) + * @param {mixed} obj the node to close recursively, omit to close all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation + * @trigger close_all.jstree + */ + close_all : function (obj, animation) { + if(!obj) { obj = $.jstree.root; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), + _this = this, i, j; + if(dom.length) { + dom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open'); + $(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); }); + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].state.opened = false; + } + /** + * triggered when an `close_all` call completes + * @event + * @name close_all.jstree + * @param {Object} node the closed node + */ + this.trigger('close_all', { "node" : obj }); + }, + /** + * checks if a node is disabled (not selectable) + * @name is_disabled(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_disabled : function (obj) { + obj = this.get_node(obj); + return obj && obj.state && obj.state.disabled; + }, + /** + * enables a node - so that it can be selected + * @name enable_node(obj) + * @param {mixed} obj the node to enable + * @trigger enable_node.jstree + */ + enable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.enable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + obj.state.disabled = false; + this.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled').attr('aria-disabled', false); + /** + * triggered when an node is enabled + * @event + * @name enable_node.jstree + * @param {Object} node the enabled node + */ + this.trigger('enable_node', { 'node' : obj }); + }, + /** + * disables a node - so that it can not be selected + * @name disable_node(obj) + * @param {mixed} obj the node to disable + * @trigger disable_node.jstree + */ + disable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.disable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + obj.state.disabled = true; + this.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled').attr('aria-disabled', true); + /** + * triggered when an node is disabled + * @event + * @name disable_node.jstree + * @param {Object} node the disabled node + */ + this.trigger('disable_node', { 'node' : obj }); + }, + /** + * determines if a node is hidden + * @name is_hidden(obj) + * @param {mixed} obj the node + */ + is_hidden : function (obj) { + obj = this.get_node(obj); + return obj.state.hidden === true; + }, + /** + * hides a node - it is still in the structure but will not be visible + * @name hide_node(obj) + * @param {mixed} obj the node to hide + * @param {Boolean} skip_redraw internal parameter controlling if redraw is called + * @trigger hide_node.jstree + */ + hide_node : function (obj, skip_redraw) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.hide_node(obj[t1], true); + } + if (!skip_redraw) { + this.redraw(); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(!obj.state.hidden) { + obj.state.hidden = true; + this._node_changed(obj.parent); + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when an node is hidden + * @event + * @name hide_node.jstree + * @param {Object} node the hidden node + */ + this.trigger('hide_node', { 'node' : obj }); + } + }, + /** + * shows a node + * @name show_node(obj) + * @param {mixed} obj the node to show + * @param {Boolean} skip_redraw internal parameter controlling if redraw is called + * @trigger show_node.jstree + */ + show_node : function (obj, skip_redraw) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.show_node(obj[t1], true); + } + if (!skip_redraw) { + this.redraw(); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(obj.state.hidden) { + obj.state.hidden = false; + this._node_changed(obj.parent); + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when an node is shown + * @event + * @name show_node.jstree + * @param {Object} node the shown node + */ + this.trigger('show_node', { 'node' : obj }); + } + }, + /** + * hides all nodes + * @name hide_all() + * @trigger hide_all.jstree + */ + hide_all : function (skip_redraw) { + var i, m = this._model.data, ids = []; + for(i in m) { + if(m.hasOwnProperty(i) && i !== $.jstree.root && !m[i].state.hidden) { + m[i].state.hidden = true; + ids.push(i); + } + } + this._model.force_full_redraw = true; + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when all nodes are hidden + * @event + * @name hide_all.jstree + * @param {Array} nodes the IDs of all hidden nodes + */ + this.trigger('hide_all', { 'nodes' : ids }); + return ids; + }, + /** + * shows all nodes + * @name show_all() + * @trigger show_all.jstree + */ + show_all : function (skip_redraw) { + var i, m = this._model.data, ids = []; + for(i in m) { + if(m.hasOwnProperty(i) && i !== $.jstree.root && m[i].state.hidden) { + m[i].state.hidden = false; + ids.push(i); + } + } + this._model.force_full_redraw = true; + if(!skip_redraw) { + this.redraw(); + } + /** + * triggered when all nodes are shown + * @event + * @name show_all.jstree + * @param {Array} nodes the IDs of all shown nodes + */ + this.trigger('show_all', { 'nodes' : ids }); + return ids; + }, + /** + * called when a node is selected by the user. Used internally. + * @private + * @name activate_node(obj, e) + * @param {mixed} obj the node + * @param {Object} e the related event + * @trigger activate_node.jstree, changed.jstree + */ + activate_node : function (obj, e) { + if(this.is_disabled(obj)) { + return false; + } + if(!e || typeof e !== 'object') { + e = {}; + } + + // ensure last_clicked is still in the DOM, make it fresh (maybe it was moved?) and make sure it is still selected, if not - make last_clicked the last selected node + this._data.core.last_clicked = this._data.core.last_clicked && this._data.core.last_clicked.id !== undefined ? this.get_node(this._data.core.last_clicked.id) : null; + if(this._data.core.last_clicked && !this._data.core.last_clicked.state.selected) { this._data.core.last_clicked = null; } + if(!this._data.core.last_clicked && this._data.core.selected.length) { this._data.core.last_clicked = this.get_node(this._data.core.selected[this._data.core.selected.length - 1]); } + + if(!this.settings.core.multiple || (!e.metaKey && !e.ctrlKey && !e.shiftKey) || (e.shiftKey && (!this._data.core.last_clicked || !this.get_parent(obj) || this.get_parent(obj) !== this._data.core.last_clicked.parent ) )) { + if(!this.settings.core.multiple && (e.metaKey || e.ctrlKey || e.shiftKey) && this.is_selected(obj)) { + this.deselect_node(obj, false, e); + } + else { + this.deselect_all(true); + this.select_node(obj, false, false, e); + this._data.core.last_clicked = this.get_node(obj); + } + } + else { + if(e.shiftKey) { + var o = this.get_node(obj).id, + l = this._data.core.last_clicked.id, + p = this.get_node(this._data.core.last_clicked.parent).children, + c = false, + i, j; + for(i = 0, j = p.length; i < j; i += 1) { + // separate IFs work whem o and l are the same + if(p[i] === o) { + c = !c; + } + if(p[i] === l) { + c = !c; + } + if(!this.is_disabled(p[i]) && (c || p[i] === o || p[i] === l)) { + if (!this.is_hidden(p[i])) { + this.select_node(p[i], true, false, e); + } + } + else { + this.deselect_node(p[i], true, e); + } + } + this.trigger('changed', { 'action' : 'select_node', 'node' : this.get_node(obj), 'selected' : this._data.core.selected, 'event' : e }); + } + else { + if(!this.is_selected(obj)) { + this.select_node(obj, false, false, e); + } + else { + this.deselect_node(obj, false, e); + } + } + } + /** + * triggered when an node is clicked or intercated with by the user + * @event + * @name activate_node.jstree + * @param {Object} node + * @param {Object} event the ooriginal event (if any) which triggered the call (may be an empty object) + */ + this.trigger('activate_node', { 'node' : this.get_node(obj), 'event' : e }); + }, + /** + * applies the hover state on a node, called when a node is hovered by the user. Used internally. + * @private + * @name hover_node(obj) + * @param {mixed} obj + * @trigger hover_node.jstree + */ + hover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || obj.children('.jstree-hovered').length) { + return false; + } + var o = this.element.find('.jstree-hovered'), t = this.element; + if(o && o.length) { this.dehover_node(o); } + + obj.children('.jstree-anchor').addClass('jstree-hovered'); + /** + * triggered when an node is hovered + * @event + * @name hover_node.jstree + * @param {Object} node + */ + this.trigger('hover_node', { 'node' : this.get_node(obj) }); + setTimeout(function () { t.attr('aria-activedescendant', obj[0].id); }, 0); + }, + /** + * removes the hover state from a nodecalled when a node is no longer hovered by the user. Used internally. + * @private + * @name dehover_node(obj) + * @param {mixed} obj + * @trigger dehover_node.jstree + */ + dehover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || !obj.children('.jstree-hovered').length) { + return false; + } + obj.children('.jstree-anchor').removeClass('jstree-hovered'); + /** + * triggered when an node is no longer hovered + * @event + * @name dehover_node.jstree + * @param {Object} node + */ + this.trigger('dehover_node', { 'node' : this.get_node(obj) }); + }, + /** + * select a node + * @name select_node(obj [, supress_event, prevent_open]) + * @param {mixed} obj an array can be used to select multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @param {Boolean} prevent_open if set to `true` parents of the selected node won't be opened + * @trigger select_node.jstree, changed.jstree + */ + select_node : function (obj, supress_event, prevent_open, e) { + var dom, t1, t2, th; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.select_node(obj[t1], supress_event, prevent_open, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.selected) { + obj.state.selected = true; + this._data.core.selected.push(obj.id); + if(!prevent_open) { + dom = this._open_to(obj); + } + if(dom && dom.length) { + dom.attr('aria-selected', true).children('.jstree-anchor').addClass('jstree-clicked'); + } + /** + * triggered when an node is selected + * @event + * @name select_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this select_node + */ + this.trigger('select_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + /** + * triggered when selection changes + * @event + * @name changed.jstree + * @param {Object} node + * @param {Object} action the action that caused the selection to change + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this changed event + */ + this.trigger('changed', { 'action' : 'select_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * deselect a node + * @name deselect_node(obj [, supress_event]) + * @param {mixed} obj an array can be used to deselect multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_node.jstree, changed.jstree + */ + deselect_node : function (obj, supress_event, e) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.deselect_node(obj[t1], supress_event, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.selected) { + obj.state.selected = false; + this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id); + if(dom.length) { + dom.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-clicked'); + } + /** + * triggered when an node is deselected + * @event + * @name deselect_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this deselect_node + */ + this.trigger('deselect_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * select all nodes in the tree + * @name select_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger select_all.jstree, changed.jstree + */ + select_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + this._data.core.selected = this._model.data[$.jstree.root].children_d.concat(); + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = true; + } + } + this.redraw(true); + /** + * triggered when all nodes are selected + * @event + * @name select_all.jstree + * @param {Array} selected the current selection + */ + this.trigger('select_all', { 'selected' : this._data.core.selected }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'select_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * deselect all selected nodes + * @name deselect_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_all.jstree, changed.jstree + */ + deselect_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = false; + } + } + this._data.core.selected = []; + this.element.find('.jstree-clicked').removeClass('jstree-clicked').parent().attr('aria-selected', false); + /** + * triggered when all nodes are deselected + * @event + * @name deselect_all.jstree + * @param {Object} node the previous selection + * @param {Array} selected the current selection + */ + this.trigger('deselect_all', { 'selected' : this._data.core.selected, 'node' : tmp }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * checks if a node is selected + * @name is_selected(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_selected : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + return obj.state.selected; + }, + /** + * get an array of all selected nodes + * @name get_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_selected : function (full) { + return full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected.slice(); + }, + /** + * get an array of all top level selected nodes (ignoring children of selected nodes) + * @name get_top_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_top_selected : function (full) { + var tmp = this.get_selected(true), + obj = {}, i, j, k, l; + for(i = 0, j = tmp.length; i < j; i++) { + obj[tmp[i].id] = tmp[i]; + } + for(i = 0, j = tmp.length; i < j; i++) { + for(k = 0, l = tmp[i].children_d.length; k < l; k++) { + if(obj[tmp[i].children_d[k]]) { + delete obj[tmp[i].children_d[k]]; + } + } + } + tmp = []; + for(i in obj) { + if(obj.hasOwnProperty(i)) { + tmp.push(i); + } + } + return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp; + }, + /** + * get an array of all bottom level selected nodes (ignoring selected parents) + * @name get_bottom_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_bottom_selected : function (full) { + var tmp = this.get_selected(true), + obj = [], i, j; + for(i = 0, j = tmp.length; i < j; i++) { + if(!tmp[i].children.length) { + obj.push(tmp[i].id); + } + } + return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj; + }, + /** + * gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally. + * @name get_state() + * @private + * @return {Object} + */ + get_state : function () { + var state = { + 'core' : { + 'open' : [], + 'scroll' : { + 'left' : this.element.scrollLeft(), + 'top' : this.element.scrollTop() + }, + /*! + 'themes' : { + 'name' : this.get_theme(), + 'icons' : this._data.core.themes.icons, + 'dots' : this._data.core.themes.dots + }, + */ + 'selected' : [] + } + }, i; + for(i in this._model.data) { + if(this._model.data.hasOwnProperty(i)) { + if(i !== $.jstree.root) { + if(this._model.data[i].state.opened) { + state.core.open.push(i); + } + if(this._model.data[i].state.selected) { + state.core.selected.push(i); + } + } + } + } + return state; + }, + /** + * sets the state of the tree. Used internally. + * @name set_state(state [, callback]) + * @private + * @param {Object} state the state to restore. Keep in mind this object is passed by reference and jstree will modify it. + * @param {Function} callback an optional function to execute once the state is restored. + * @trigger set_state.jstree + */ + set_state : function (state, callback) { + if(state) { + if(state.core) { + var res, n, t, _this, i; + if(state.core.open) { + if(!$.isArray(state.core.open) || !state.core.open.length) { + delete state.core.open; + this.set_state(state, callback); + } + else { + this._load_nodes(state.core.open, function (nodes) { + this.open_node(nodes, false, 0); + delete state.core.open; + this.set_state(state, callback); + }); + } + return false; + } + if(state.core.scroll) { + if(state.core.scroll && state.core.scroll.left !== undefined) { + this.element.scrollLeft(state.core.scroll.left); + } + if(state.core.scroll && state.core.scroll.top !== undefined) { + this.element.scrollTop(state.core.scroll.top); + } + delete state.core.scroll; + this.set_state(state, callback); + return false; + } + if(state.core.selected) { + _this = this; + this.deselect_all(); + $.each(state.core.selected, function (i, v) { + _this.select_node(v, false, true); + }); + delete state.core.selected; + this.set_state(state, callback); + return false; + } + for(i in state) { + if(state.hasOwnProperty(i) && i !== "core" && $.inArray(i, this.settings.plugins) === -1) { + delete state[i]; + } + } + if($.isEmptyObject(state.core)) { + delete state.core; + this.set_state(state, callback); + return false; + } + } + if($.isEmptyObject(state)) { + state = null; + if(callback) { callback.call(this); } + /** + * triggered when a `set_state` call completes + * @event + * @name set_state.jstree + */ + this.trigger('set_state'); + return false; + } + return true; + } + return false; + }, + /** + * refreshes the tree - all nodes are reloaded with calls to `load_node`. + * @name refresh() + * @param {Boolean} skip_loading an option to skip showing the loading indicator + * @param {Mixed} forget_state if set to `true` state will not be reapplied, if set to a function (receiving the current state as argument) the result of that function will be used as state + * @trigger refresh.jstree + */ + refresh : function (skip_loading, forget_state) { + this._data.core.state = forget_state === true ? {} : this.get_state(); + if(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); } + this._cnt = 0; + this._model.data = {}; + this._model.data[$.jstree.root] = { + id : $.jstree.root, + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + }; + this._data.core.selected = []; + this._data.core.last_clicked = null; + this._data.core.focused = null; + + var c = this.get_container_ul()[0].className; + if(!skip_loading) { + this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>"); + this.element.attr('aria-activedescendant','j'+this._id+'_loading'); + } + this.load_node($.jstree.root, function (o, s) { + if(s) { + this.get_container_ul()[0].className = c; + if(this._firstChild(this.get_container_ul()[0])) { + this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id); + } + this.set_state($.extend(true, {}, this._data.core.state), function () { + /** + * triggered when a `refresh` call completes + * @event + * @name refresh.jstree + */ + this.trigger('refresh'); + }); + } + this._data.core.state = null; + }); + }, + /** + * refreshes a node in the tree (reload its children) all opened nodes inside that node are reloaded with calls to `load_node`. + * @name refresh_node(obj) + * @param {mixed} obj the node + * @trigger refresh_node.jstree + */ + refresh_node : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var opened = [], to_load = [], s = this._data.core.selected.concat([]); + to_load.push(obj.id); + if(obj.state.opened === true) { opened.push(obj.id); } + this.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); }); + this._load_nodes(to_load, $.proxy(function (nodes) { + this.open_node(opened, false, 0); + this.select_node(s); + /** + * triggered when a node is refreshed + * @event + * @name refresh_node.jstree + * @param {Object} node - the refreshed node + * @param {Array} nodes - an array of the IDs of the nodes that were reloaded + */ + this.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes }); + }, this), false, true); + }, + /** + * set (change) the ID of a node + * @name set_id(obj, id) + * @param {mixed} obj the node + * @param {String} id the new ID + * @return {Boolean} + * @trigger set_id.jstree + */ + set_id : function (obj, id) { + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + var i, j, m = this._model.data, old = obj.id; + id = id.toString(); + // update parents (replace current ID with new one in children and children_d) + m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id; + for(i = 0, j = obj.parents.length; i < j; i++) { + m[obj.parents[i]].children_d[$.inArray(obj.id, m[obj.parents[i]].children_d)] = id; + } + // update children (replace current ID with new one in parent and parents) + for(i = 0, j = obj.children.length; i < j; i++) { + m[obj.children[i]].parent = id; + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + m[obj.children_d[i]].parents[$.inArray(obj.id, m[obj.children_d[i]].parents)] = id; + } + i = $.inArray(obj.id, this._data.core.selected); + if(i !== -1) { this._data.core.selected[i] = id; } + // update model and obj itself (obj.id, this._model.data[KEY]) + i = this.get_node(obj.id, true); + if(i) { + i.attr('id', id); //.children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor'); + if(this.element.attr('aria-activedescendant') === obj.id) { + this.element.attr('aria-activedescendant', id); + } + } + delete m[obj.id]; + obj.id = id; + obj.li_attr.id = id; + m[id] = obj; + /** + * triggered when a node id value is changed + * @event + * @name set_id.jstree + * @param {Object} node + * @param {String} old the old id + */ + this.trigger('set_id',{ "node" : obj, "new" : obj.id, "old" : old }); + return true; + }, + /** + * get the text value of a node + * @name get_text(obj) + * @param {mixed} obj the node + * @return {String} + */ + get_text : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === $.jstree.root) ? false : obj.text; + }, + /** + * set the text value of a node. Used internally, please use `rename_node(obj, val)`. + * @private + * @name set_text(obj, val) + * @param {mixed} obj the node, you can pass an array to set the text on multiple nodes + * @param {String} val the new text value + * @return {Boolean} + * @trigger set_text.jstree + */ + set_text : function (obj, val) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_text(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + obj.text = val; + if(this.get_node(obj, true).length) { + this.redraw_node(obj.id); + } + /** + * triggered when a node text value is changed + * @event + * @name set_text.jstree + * @param {Object} obj + * @param {String} text the new value + */ + this.trigger('set_text',{ "obj" : obj, "text" : val }); + return true; + }, + /** + * gets a JSON representation of a node (or the whole tree) + * @name get_json([obj, options]) + * @param {mixed} obj + * @param {Object} options + * @param {Boolean} options.no_state do not return state information + * @param {Boolean} options.no_id do not return ID + * @param {Boolean} options.no_children do not include children + * @param {Boolean} options.no_data do not include node data + * @param {Boolean} options.no_li_attr do not include LI attributes + * @param {Boolean} options.no_a_attr do not include A attributes + * @param {Boolean} options.flat return flat JSON instead of nested + * @return {Object} + */ + get_json : function (obj, options, flat) { + obj = this.get_node(obj || $.jstree.root); + if(!obj) { return false; } + if(options && options.flat && !flat) { flat = []; } + var tmp = { + 'id' : obj.id, + 'text' : obj.text, + 'icon' : this.get_icon(obj), + 'li_attr' : $.extend(true, {}, obj.li_attr), + 'a_attr' : $.extend(true, {}, obj.a_attr), + 'state' : {}, + 'data' : options && options.no_data ? false : $.extend(true, {}, obj.data) + //( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ), + }, i, j; + if(options && options.flat) { + tmp.parent = obj.parent; + } + else { + tmp.children = []; + } + if(!options || !options.no_state) { + for(i in obj.state) { + if(obj.state.hasOwnProperty(i)) { + tmp.state[i] = obj.state[i]; + } + } + } else { + delete tmp.state; + } + if(options && options.no_li_attr) { + delete tmp.li_attr; + } + if(options && options.no_a_attr) { + delete tmp.a_attr; + } + if(options && options.no_id) { + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + if(tmp.a_attr && tmp.a_attr.id) { + delete tmp.a_attr.id; + } + } + if(options && options.flat && obj.id !== $.jstree.root) { + flat.push(tmp); + } + if(!options || !options.no_children) { + for(i = 0, j = obj.children.length; i < j; i++) { + if(options && options.flat) { + this.get_json(obj.children[i], options, flat); + } + else { + tmp.children.push(this.get_json(obj.children[i], options)); + } + } + } + return options && options.flat ? flat : (obj.id === $.jstree.root ? tmp.children : tmp); + }, + /** + * create a new node (do not confuse with load_node) + * @name create_node([par, node, pos, callback, is_loaded]) + * @param {mixed} par the parent node (to create a root node use either "#" (string) or `null`) + * @param {mixed} node the data for the new node (a valid JSON object, or a simple string with the name) + * @param {mixed} pos the index at which to insert the node, "first" and "last" are also supported, default is "last" + * @param {Function} callback a function to be called once the node is created + * @param {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded + * @return {String} the ID of the newly create node + * @trigger model.jstree, create_node.jstree + */ + create_node : function (par, node, pos, callback, is_loaded) { + if(par === null) { par = $.jstree.root; } + par = this.get_node(par); + if(!par) { return false; } + pos = pos === undefined ? "last" : pos; + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.create_node(par, node, pos, callback, true); }); + } + if(!node) { node = { "text" : this.get_string('New node') }; } + if(typeof node === "string") { node = { "text" : node }; } + if(node.text === undefined) { node.text = this.get_string('New node'); } + var tmp, dpc, i, j; + + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children); + par = tmp; + break; + case "after" : + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children) + 1; + par = tmp; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > par.children.length) { pos = par.children.length; } + if(!node.id) { node.id = true; } + if(!this.check("create_node", node, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, par.id, par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : par.id }); + + par.children_d = par.children_d.concat(dpc); + for(i = 0, j = par.parents.length; i < j; i++) { + this._model.data[par.parents[i]].children_d = this._model.data[par.parents[i]].children_d.concat(dpc); + } + node = tmp; + tmp = []; + for(i = 0, j = par.children.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = par.children[i]; + } + tmp[pos] = node.id; + par.children = tmp; + + this.redraw_node(par, true); + if(callback) { callback.call(this, this.get_node(node)); } + /** + * triggered when a node is created + * @event + * @name create_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the new node among the parent's children + */ + this.trigger('create_node', { "node" : this.get_node(node), "parent" : par.id, "position" : pos }); + return node.id; + }, + /** + * set the text value of a node + * @name rename_node(obj, val) + * @param {mixed} obj the node, you can pass an array to rename multiple nodes to the same name + * @param {String} val the new text value + * @return {Boolean} + * @trigger rename_node.jstree + */ + rename_node : function (obj, val) { + var t1, t2, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.rename_node(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + old = obj.text; + if(!this.check("rename_node", obj, this.get_parent(obj), val)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + this.set_text(obj, val); // .apply(this, Array.prototype.slice.call(arguments)) + /** + * triggered when a node is renamed + * @event + * @name rename_node.jstree + * @param {Object} node + * @param {String} text the new value + * @param {String} old the old value + */ + this.trigger('rename_node', { "node" : obj, "text" : val, "old" : old }); + return true; + }, + /** + * remove a node + * @name delete_node(obj) + * @param {mixed} obj the node, you can pass an array to delete multiple nodes + * @return {Boolean} + * @trigger delete_node.jstree, changed.jstree + */ + delete_node : function (obj) { + var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.delete_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + par = this.get_node(obj.parent); + pos = $.inArray(obj.id, par.children); + c = false; + if(!this.check("delete_node", obj, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(pos !== -1) { + par.children = $.vakata.array_remove(par.children, pos); + } + tmp = obj.children_d.concat([]); + tmp.push(obj.id); + for(i = 0, j = obj.parents.length; i < j; i++) { + this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) { + return $.inArray(v, tmp) === -1; + }); + } + for(k = 0, l = tmp.length; k < l; k++) { + if(this._model.data[tmp[k]].state.selected) { + c = true; + break; + } + } + if (c) { + this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) { + return $.inArray(v, tmp) === -1; + }); + } + /** + * triggered when a node is deleted + * @event + * @name delete_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + */ + this.trigger('delete_node', { "node" : obj, "parent" : par.id }); + if(c) { + this.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id }); + } + for(k = 0, l = tmp.length; k < l; k++) { + delete this._model.data[tmp[k]]; + } + if($.inArray(this._data.core.focused, tmp) !== -1) { + this._data.core.focused = null; + top = this.element[0].scrollTop; + lft = this.element[0].scrollLeft; + if(par.id === $.jstree.root) { + if (this._model.data[$.jstree.root].children[0]) { + this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus(); + } + } + else { + this.get_node(par, true).children('.jstree-anchor').focus(); + } + this.element[0].scrollTop = top; + this.element[0].scrollLeft = lft; + } + this.redraw_node(par, true); + return true; + }, + /** + * check if an operation is premitted on the tree. Used internally. + * @private + * @name check(chk, obj, par, pos) + * @param {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node" + * @param {mixed} obj the node + * @param {mixed} par the parent + * @param {mixed} pos the position to insert at, or if "rename_node" - the new name + * @param {mixed} more some various additional information, for example if a "move_node" operations is triggered by DND this will be the hovered node + * @return {Boolean} + */ + check : function (chk, obj, par, pos, more) { + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj, + chc = this.settings.core.check_callback; + if(chk === "move_node" || chk === "copy_node") { + if((!more || !more.is_multi) && (obj.id === par.id || (chk === "move_node" && $.inArray(obj.id, par.children) === pos) || $.inArray(par.id, obj.children_d) !== -1)) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + } + if(tmp && tmp.data) { tmp = tmp.data; } + if(tmp && tmp.functions && (tmp.functions[chk] === false || tmp.functions[chk] === true)) { + if(tmp.functions[chk] === false) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_02', 'reason' : 'Node data prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return tmp.functions[chk]; + } + if(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + return true; + }, + /** + * get the last error + * @name last_error() + * @return {Object} + */ + last_error : function () { + return this._data.core.last_error; + }, + /** + * move a node to a new parent + * @name move_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to move, pass an array to move multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} is_loaded internal parameter indicating if the parent node has been loaded + * @param {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn + * @param {Boolean} instance internal parameter indicating if the node comes from another instance + * @trigger move_node.jstree + */ + move_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) { + var t1, t2, old_par, old_pos, new_par, old_ins, is_multi, dpc, tmp, i, j, k, l, p; + + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + if(!par) { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.move_node(obj, par, pos, callback, true, false, origin); }); + } + + if($.isArray(obj)) { + if(obj.length === 1) { + obj = obj[0]; + } + else { + //obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + if((tmp = this.move_node(obj[t1], par, pos, callback, is_loaded, false, origin))) { + par = tmp; + pos = "after"; + } + } + this.redraw(); + return true; + } + } + obj = obj && obj.id ? obj : this.get_node(obj); + + if(!obj || obj.id === $.jstree.root) { return false; } + + old_par = (obj.parent || $.jstree.root).toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent); + old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id)); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + old_pos = old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1; + if(old_ins && old_ins._id) { + obj = old_ins._model.data[obj.id]; + } + + if(is_multi) { + if((tmp = this.copy_node(obj, par, pos, callback, is_loaded, false, origin))) { + if(old_ins) { old_ins.delete_node(obj); } + return tmp; + } + return false; + } + //var m = this._model.data; + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("move_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(obj.parent === new_par.id) { + dpc = new_par.children.concat(); + tmp = $.inArray(obj.id, dpc); + if(tmp !== -1) { + dpc = $.vakata.array_remove(dpc, tmp); + if(pos > tmp) { pos--; } + } + tmp = []; + for(i = 0, j = dpc.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = dpc[i]; + } + tmp[pos] = obj.id; + new_par.children = tmp; + this._node_changed(new_par.id); + this.redraw(new_par.id === $.jstree.root); + } + else { + // clean old parent and up + tmp = obj.children_d.concat(); + tmp.push(obj.id); + for(i = 0, j = obj.parents.length; i < j; i++) { + dpc = []; + p = old_ins._model.data[obj.parents[i]].children_d; + for(k = 0, l = p.length; k < l; k++) { + if($.inArray(p[k], tmp) === -1) { + dpc.push(p[k]); + } + } + old_ins._model.data[obj.parents[i]].children_d = dpc; + } + old_ins._model.data[old_par].children = $.vakata.array_remove_item(old_ins._model.data[old_par].children, obj.id); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(tmp); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = obj.id; + new_par.children = dpc; + new_par.children_d.push(obj.id); + new_par.children_d = new_par.children_d.concat(obj.children_d); + + // update object + obj.parent = new_par.id; + tmp = new_par.parents.concat(); + tmp.unshift(new_par.id); + p = obj.parents.length; + obj.parents = tmp; + + // update object children + tmp = tmp.concat(); + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1); + Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp); + } + + if(old_par === $.jstree.root || new_par.id === $.jstree.root) { + this._model.force_full_redraw = true; + } + if(!this._model.force_full_redraw) { + this._node_changed(old_par); + this._node_changed(new_par.id); + } + if(!skip_redraw) { + this.redraw(); + } + } + if(callback) { callback.call(this, obj, new_par, pos); } + /** + * triggered when a node is moved + * @event + * @name move_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Number} old_position the old position of the node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('move_node', { "node" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_pos, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this }); + return obj.id; + }, + /** + * copy a node to a new parent + * @name copy_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to copy, pass an array to copy multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at (besides integer values, "first" and "last" are supported, as well as "before" and "after"), defaults to integer `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} is_loaded internal parameter indicating if the parent node has been loaded + * @param {Boolean} skip_redraw internal parameter indicating if the tree should be redrawn + * @param {Boolean} instance internal parameter indicating if the node comes from another instance + * @trigger model.jstree copy_node.jstree + */ + copy_node : function (obj, par, pos, callback, is_loaded, skip_redraw, origin) { + var t1, t2, dpc, tmp, i, j, node, old_par, new_par, old_ins, is_multi; + + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + if(!par) { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true, false, origin); }); + } + + if($.isArray(obj)) { + if(obj.length === 1) { + obj = obj[0]; + } + else { + //obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + if((tmp = this.copy_node(obj[t1], par, pos, callback, is_loaded, true, origin))) { + par = tmp; + pos = "after"; + } + } + this.redraw(); + return true; + } + } + obj = obj && obj.id ? obj : this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + + old_par = (obj.parent || $.jstree.root).toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent); + old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id)); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + + if(old_ins && old_ins._id) { + obj = old_ins._model.data[obj.id]; + } + + if(par.id === $.jstree.root) { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("copy_node", obj, new_par, pos, { 'core' : true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + node = old_ins ? old_ins.get_json(obj, { no_id : true, no_data : true, no_state : true }) : obj; + if(!node) { return false; } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, new_par.id, new_par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + if(obj && obj.state && obj.state.loaded === false) { tmp.state.loaded = false; } + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : new_par.id }); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(dpc); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = tmp.id; + new_par.children = dpc; + new_par.children_d.push(tmp.id); + new_par.children_d = new_par.children_d.concat(tmp.children_d); + + if(new_par.id === $.jstree.root) { + this._model.force_full_redraw = true; + } + if(!this._model.force_full_redraw) { + this._node_changed(new_par.id); + } + if(!skip_redraw) { + this.redraw(new_par.id === $.jstree.root); + } + if(callback) { callback.call(this, tmp, new_par, pos); } + /** + * triggered when a node is copied + * @event + * @name copy_node.jstree + * @param {Object} node the copied node + * @param {Object} original the original node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Number} old_position the position of the original node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('copy_node', { "node" : tmp, "original" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_ins && old_ins._id && old_par && old_ins._model.data[old_par] && old_ins._model.data[old_par].children ? $.inArray(obj.id, old_ins._model.data[old_par].children) : -1,'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this }); + return tmp.id; + }, + /** + * cut a node (a later call to `paste(obj)` would move the node) + * @name cut(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger cut.jstree + */ + cut : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'move_node'; + /** + * triggered when nodes are added to the buffer for moving + * @event + * @name cut.jstree + * @param {Array} node + */ + this.trigger('cut', { "node" : obj }); + }, + /** + * copy a node (a later call to `paste(obj)` would copy the node) + * @name copy(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger copy.jstree + */ + copy : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'copy_node'; + /** + * triggered when nodes are added to the buffer for copying + * @event + * @name copy.jstree + * @param {Array} node + */ + this.trigger('copy', { "node" : obj }); + }, + /** + * get the current buffer (any nodes that are waiting for a paste operation) + * @name get_buffer() + * @return {Object} an object consisting of `mode` ("copy_node" or "move_node"), `node` (an array of objects) and `inst` (the instance) + */ + get_buffer : function () { + return { 'mode' : ccp_mode, 'node' : ccp_node, 'inst' : ccp_inst }; + }, + /** + * check if there is something in the buffer to paste + * @name can_paste() + * @return {Boolean} + */ + can_paste : function () { + return ccp_mode !== false && ccp_node !== false; // && ccp_inst._model.data[ccp_node]; + }, + /** + * copy or move the previously cut or copied nodes to a new parent + * @name paste(obj [, pos]) + * @param {mixed} obj the new parent + * @param {mixed} pos the position to insert at (besides integer, "first" and "last" are supported), defaults to integer `0` + * @trigger paste.jstree + */ + paste : function (obj, pos) { + obj = this.get_node(obj); + if(!obj || !ccp_mode || !ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; } + if(this[ccp_mode](ccp_node, obj, pos, false, false, false, ccp_inst)) { + /** + * triggered when paste is invoked + * @event + * @name paste.jstree + * @param {String} parent the ID of the receiving node + * @param {Array} node the nodes in the buffer + * @param {String} mode the performed operation - "copy_node" or "move_node" + */ + this.trigger('paste', { "parent" : obj.id, "node" : ccp_node, "mode" : ccp_mode }); + } + ccp_node = false; + ccp_mode = false; + ccp_inst = false; + }, + /** + * clear the buffer of previously copied or cut nodes + * @name clear_buffer() + * @trigger clear_buffer.jstree + */ + clear_buffer : function () { + ccp_node = false; + ccp_mode = false; + ccp_inst = false; + /** + * triggered when the copy / cut buffer is cleared + * @event + * @name clear_buffer.jstree + */ + this.trigger('clear_buffer'); + }, + /** + * put a node in edit mode (input field to rename the node) + * @name edit(obj [, default_text, callback]) + * @param {mixed} obj + * @param {String} default_text the text to populate the input with (if omitted or set to a non-string value the node's text value is used) + * @param {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise) and a boolean indicating if the user cancelled the edit. You can access the node's title using .text + */ + edit : function (obj, default_text, callback) { + var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false; + obj = this.get_node(obj); + if(!obj) { return false; } + if(this.settings.core.check_callback === false) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_07', 'reason' : 'Could not edit node because of check_callback' }; + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + tmp = obj; + default_text = typeof default_text === 'string' ? default_text : obj.text; + this.set_text(obj, ""); + obj = this._open_to(obj); + tmp.text = default_text; + + rtl = this._data.core.rtl; + w = this.element.width(); + this._data.core.focused = tmp.id; + a = obj.children('.jstree-anchor').focus(); + s = $('<span>'); + /*! + oi = obj.children("i:visible"), + ai = a.children("i:visible"), + w1 = oi.width() * oi.length, + w2 = ai.width() * ai.length, + */ + t = default_text; + h1 = $("<"+"div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"); + h2 = $("<"+"input />", { + "value" : t, + "class" : "jstree-rename-input", + // "size" : t.length, + "css" : { + "padding" : "0", + "border" : "1px solid silver", + "box-sizing" : "border-box", + "display" : "inline-block", + "height" : (this._data.core.li_height) + "px", + "lineHeight" : (this._data.core.li_height) + "px", + "width" : "150px" // will be set a bit further down + }, + "blur" : $.proxy(function (e) { + e.stopImmediatePropagation(); + e.preventDefault(); + var i = s.children(".jstree-rename-input"), + v = i.val(), + f = this.settings.core.force_text, + nv; + if(v === "") { v = t; } + h1.remove(); + s.replaceWith(a); + s.remove(); + t = f ? t : $('<div></div>').append($.parseHTML(t)).html(); + this.set_text(obj, t); + nv = !!this.rename_node(obj, f ? $('<div></div>').text(v).text() : $('<div></div>').append($.parseHTML(v)).html()); + if(!nv) { + this.set_text(obj, t); // move this up? and fix #483 + } + this._data.core.focused = tmp.id; + setTimeout($.proxy(function () { + var node = this.get_node(tmp.id, true); + if(node.length) { + this._data.core.focused = tmp.id; + node.children('.jstree-anchor').focus(); + } + }, this), 0); + if(callback) { + callback.call(this, tmp, nv, cancel); + } + h2 = null; + }, this), + "keydown" : function (e) { + var key = e.which; + if(key === 27) { + cancel = true; + this.value = t; + } + if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) { + e.stopImmediatePropagation(); + } + if(key === 27 || key === 13) { + e.preventDefault(); + this.blur(); + } + }, + "click" : function (e) { e.stopImmediatePropagation(); }, + "mousedown" : function (e) { e.stopImmediatePropagation(); }, + "keyup" : function (e) { + h2.width(Math.min(h1.text("pW" + this.value).width(),w)); + }, + "keypress" : function(e) { + if(e.which === 13) { return false; } + } + }); + fn = { + fontFamily : a.css('fontFamily') || '', + fontSize : a.css('fontSize') || '', + fontWeight : a.css('fontWeight') || '', + fontStyle : a.css('fontStyle') || '', + fontStretch : a.css('fontStretch') || '', + fontVariant : a.css('fontVariant') || '', + letterSpacing : a.css('letterSpacing') || '', + wordSpacing : a.css('wordSpacing') || '' + }; + s.attr('class', a.attr('class')).append(a.contents().clone()).append(h2); + a.replaceWith(s); + h1.css(fn); + h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select(); + $(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) { + if (h2 && e.target !== h2) { + $(h2).blur(); + } + }); + }, + + + /** + * changes the theme + * @name set_theme(theme_name [, theme_url]) + * @param {String} theme_name the name of the new theme to apply + * @param {mixed} theme_url the location of the CSS file for this theme. Omit or set to `false` if you manually included the file. Set to `true` to autoload from the `core.themes.dir` directory. + * @trigger set_theme.jstree + */ + set_theme : function (theme_name, theme_url) { + if(!theme_name) { return false; } + if(theme_url === true) { + var dir = this.settings.core.themes.dir; + if(!dir) { dir = $.jstree.path + '/themes'; } + theme_url = dir + '/' + theme_name + '/style.css'; + } + if(theme_url && $.inArray(theme_url, themes_loaded) === -1) { + $('head').append('<'+'link rel="stylesheet" href="' + theme_url + '" type="text/css" />'); + themes_loaded.push(theme_url); + } + if(this._data.core.themes.name) { + this.element.removeClass('jstree-' + this._data.core.themes.name); + } + this._data.core.themes.name = theme_name; + this.element.addClass('jstree-' + theme_name); + this.element[this.settings.core.themes.responsive ? 'addClass' : 'removeClass' ]('jstree-' + theme_name + '-responsive'); + /** + * triggered when a theme is set + * @event + * @name set_theme.jstree + * @param {String} theme the new theme + */ + this.trigger('set_theme', { 'theme' : theme_name }); + }, + /** + * gets the name of the currently applied theme name + * @name get_theme() + * @return {String} + */ + get_theme : function () { return this._data.core.themes.name; }, + /** + * changes the theme variant (if the theme has variants) + * @name set_theme_variant(variant_name) + * @param {String|Boolean} variant_name the variant to apply (if `false` is used the current variant is removed) + */ + set_theme_variant : function (variant_name) { + if(this._data.core.themes.variant) { + this.element.removeClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + this._data.core.themes.variant = variant_name; + if(variant_name) { + this.element.addClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + }, + /** + * gets the name of the currently applied theme variant + * @name get_theme() + * @return {String} + */ + get_theme_variant : function () { return this._data.core.themes.variant; }, + /** + * shows a striped background on the container (if the theme supports it) + * @name show_stripes() + */ + show_stripes : function () { + this._data.core.themes.stripes = true; + this.get_container_ul().addClass("jstree-striped"); + /** + * triggered when stripes are shown + * @event + * @name show_stripes.jstree + */ + this.trigger('show_stripes'); + }, + /** + * hides the striped background on the container + * @name hide_stripes() + */ + hide_stripes : function () { + this._data.core.themes.stripes = false; + this.get_container_ul().removeClass("jstree-striped"); + /** + * triggered when stripes are hidden + * @event + * @name hide_stripes.jstree + */ + this.trigger('hide_stripes'); + }, + /** + * toggles the striped background on the container + * @name toggle_stripes() + */ + toggle_stripes : function () { if(this._data.core.themes.stripes) { this.hide_stripes(); } else { this.show_stripes(); } }, + /** + * shows the connecting dots (if the theme supports it) + * @name show_dots() + */ + show_dots : function () { + this._data.core.themes.dots = true; + this.get_container_ul().removeClass("jstree-no-dots"); + /** + * triggered when dots are shown + * @event + * @name show_dots.jstree + */ + this.trigger('show_dots'); + }, + /** + * hides the connecting dots + * @name hide_dots() + */ + hide_dots : function () { + this._data.core.themes.dots = false; + this.get_container_ul().addClass("jstree-no-dots"); + /** + * triggered when dots are hidden + * @event + * @name hide_dots.jstree + */ + this.trigger('hide_dots'); + }, + /** + * toggles the connecting dots + * @name toggle_dots() + */ + toggle_dots : function () { if(this._data.core.themes.dots) { this.hide_dots(); } else { this.show_dots(); } }, + /** + * show the node icons + * @name show_icons() + */ + show_icons : function () { + this._data.core.themes.icons = true; + this.get_container_ul().removeClass("jstree-no-icons"); + /** + * triggered when icons are shown + * @event + * @name show_icons.jstree + */ + this.trigger('show_icons'); + }, + /** + * hide the node icons + * @name hide_icons() + */ + hide_icons : function () { + this._data.core.themes.icons = false; + this.get_container_ul().addClass("jstree-no-icons"); + /** + * triggered when icons are hidden + * @event + * @name hide_icons.jstree + */ + this.trigger('hide_icons'); + }, + /** + * toggle the node icons + * @name toggle_icons() + */ + toggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }, + /** + * show the node ellipsis + * @name show_icons() + */ + show_ellipsis : function () { + this._data.core.themes.ellipsis = true; + this.get_container_ul().addClass("jstree-ellipsis"); + /** + * triggered when ellisis is shown + * @event + * @name show_ellipsis.jstree + */ + this.trigger('show_ellipsis'); + }, + /** + * hide the node ellipsis + * @name hide_ellipsis() + */ + hide_ellipsis : function () { + this._data.core.themes.ellipsis = false; + this.get_container_ul().removeClass("jstree-ellipsis"); + /** + * triggered when ellisis is hidden + * @event + * @name hide_ellipsis.jstree + */ + this.trigger('hide_ellipsis'); + }, + /** + * toggle the node ellipsis + * @name toggle_icons() + */ + toggle_ellipsis : function () { if(this._data.core.themes.ellipsis) { this.hide_ellipsis(); } else { this.show_ellipsis(); } }, + /** + * set the node icon for a node + * @name set_icon(obj, icon) + * @param {mixed} obj + * @param {String} icon the new icon - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + */ + set_icon : function (obj, icon) { + var t1, t2, dom, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_icon(obj[t1], icon); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { return false; } + old = obj.icon; + obj.icon = icon === true || icon === null || icon === undefined || icon === '' ? true : icon; + dom = this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon"); + if(icon === false) { + this.hide_icon(obj); + } + else if(icon === true || icon === null || icon === undefined || icon === '') { + dom.removeClass('jstree-themeicon-custom ' + old).css("background","").removeAttr("rel"); + if(old === false) { this.show_icon(obj); } + } + else if(icon.indexOf("/") === -1 && icon.indexOf(".") === -1) { + dom.removeClass(old).css("background",""); + dom.addClass(icon + ' jstree-themeicon-custom').attr("rel",icon); + if(old === false) { this.show_icon(obj); } + } + else { + dom.removeClass(old).css("background",""); + dom.addClass('jstree-themeicon-custom').css("background", "url('" + icon + "') center center no-repeat").attr("rel",icon); + if(old === false) { this.show_icon(obj); } + } + return true; + }, + /** + * get the node icon for a node + * @name get_icon(obj) + * @param {mixed} obj + * @return {String} + */ + get_icon : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === $.jstree.root) ? false : obj.icon; + }, + /** + * hide the icon on an individual node + * @name hide_icon(obj) + * @param {mixed} obj + */ + hide_icon : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.hide_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === $.jstree.root) { return false; } + obj.icon = false; + this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon").addClass('jstree-themeicon-hidden'); + return true; + }, + /** + * show the icon on an individual node + * @name show_icon(obj) + * @param {mixed} obj + */ + show_icon : function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.show_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === $.jstree.root) { return false; } + dom = this.get_node(obj, true); + obj.icon = dom.length ? dom.children(".jstree-anchor").children(".jstree-themeicon").attr('rel') : true; + if(!obj.icon) { obj.icon = true; } + dom.children(".jstree-anchor").children(".jstree-themeicon").removeClass('jstree-themeicon-hidden'); + return true; + } + }; + + // helpers + $.vakata = {}; + // collect attributes + $.vakata.attributes = function(node, with_values) { + node = $(node)[0]; + var attr = with_values ? {} : []; + if(node && node.attributes) { + $.each(node.attributes, function (i, v) { + if($.inArray(v.name.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; } + if(v.value !== null && $.trim(v.value) !== '') { + if(with_values) { attr[v.name] = v.value; } + else { attr.push(v.name); } + } + }); + } + return attr; + }; + $.vakata.array_unique = function(array) { + var a = [], i, j, l, o = {}; + for(i = 0, l = array.length; i < l; i++) { + if(o[array[i]] === undefined) { + a.push(array[i]); + o[array[i]] = true; + } + } + return a; + }; + // remove item from array + $.vakata.array_remove = function(array, from) { + array.splice(from, 1); + return array; + //var rest = array.slice((to || from) + 1 || array.length); + //array.length = from < 0 ? array.length + from : from; + //array.push.apply(array, rest); + //return array; + }; + // remove item from array + $.vakata.array_remove_item = function(array, item) { + var tmp = $.inArray(item, array); + return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array; + }; + $.vakata.array_filter = function(c,a,b,d,e) { + if (c.filter) { + return c.filter(a, b); + } + d=[]; + for (e in c) { + if (~~e+''===e+'' && e>=0 && a.call(b,c[e],+e,c)) { + d.push(c[e]); + } + } + return d; + }; +})); diff --git a/civicrm/bower_components/jstree/src/jstree.massload.js b/civicrm/bower_components/jstree/src/jstree.massload.js new file mode 100644 index 0000000000000000000000000000000000000000..d202a3eca5fb57edb3ab1da45b7b949994b6dbde --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.massload.js @@ -0,0 +1,137 @@ +/** + * ### Massload plugin + * + * Adds massload functionality to jsTree, so that multiple nodes can be loaded in a single request (only useful with lazy loading). + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.massload', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.massload) { return; } + + /** + * massload configuration + * + * It is possible to set this to a standard jQuery-like AJAX config. + * In addition to the standard jQuery ajax options here you can supply functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node IDs need to be loaded, the return value of those functions will be used. + * + * You can also set this to a function, that function will receive the node IDs being loaded as argument and a second param which is a function (callback) which should be called with the result. + * + * Both the AJAX and the function approach rely on the same return value - an object where the keys are the node IDs, and the value is the children of that node as an array. + * + * { + * "id1" : [{ "text" : "Child of ID1", "id" : "c1" }, { "text" : "Another child of ID1", "id" : "c2" }], + * "id2" : [{ "text" : "Child of ID2", "id" : "c3" }] + * } + * + * @name $.jstree.defaults.massload + * @plugin massload + */ + $.jstree.defaults.massload = null; + $.jstree.plugins.massload = function (options, parent) { + this.init = function (el, options) { + this._data.massload = {}; + parent.init.call(this, el, options); + }; + this._load_nodes = function (nodes, callback, is_callback, force_reload) { + var s = this.settings.massload, + nodesString = JSON.stringify(nodes), + toLoad = [], + m = this._model.data, + i, j, dom; + if (!is_callback) { + for(i = 0, j = nodes.length; i < j; i++) { + if(!m[nodes[i]] || ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || force_reload) ) { + toLoad.push(nodes[i]); + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.addClass("jstree-loading").attr('aria-busy',true); + } + } + } + this._data.massload = {}; + if (toLoad.length) { + if($.isFunction(s)) { + return s.call(this, toLoad, $.proxy(function (data) { + var i, j; + if(data) { + for(i in data) { + if(data.hasOwnProperty(i)) { + this._data.massload[i] = data[i]; + } + } + } + for(i = 0, j = nodes.length; i < j; i++) { + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + } + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)); + } + if(typeof s === 'object' && s && s.url) { + s = $.extend(true, {}, s); + if($.isFunction(s.url)) { + s.url = s.url.call(this, toLoad); + } + if($.isFunction(s.data)) { + s.data = s.data.call(this, toLoad); + } + return $.ajax(s) + .done($.proxy(function (data,t,x) { + var i, j; + if(data) { + for(i in data) { + if(data.hasOwnProperty(i)) { + this._data.massload[i] = data[i]; + } + } + } + for(i = 0, j = nodes.length; i < j; i++) { + dom = this.get_node(nodes[i], true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + } + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)) + .fail($.proxy(function (f) { + parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }, this)); + } + } + } + return parent._load_nodes.call(this, nodes, callback, is_callback, force_reload); + }; + this._load_node = function (obj, callback) { + var data = this._data.massload[obj.id], + rslt = null, dom; + if(data) { + rslt = this[typeof data === 'string' ? '_append_html_data' : '_append_json_data']( + obj, + typeof data === 'string' ? $($.parseHTML(data)).filter(function () { return this.nodeType !== 3; }) : data, + function (status) { callback.call(this, status); } + ); + dom = this.get_node(obj.id, true); + if (dom && dom.length) { + dom.removeClass("jstree-loading").attr('aria-busy',false); + } + delete this._data.massload[obj.id]; + return rslt; + } + return parent._load_node.call(this, obj, callback); + }; + }; +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.search.js b/civicrm/bower_components/jstree/src/jstree.search.js new file mode 100644 index 0000000000000000000000000000000000000000..21c3e7923a96bec3234c2ad028fac066e57c57a2 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.search.js @@ -0,0 +1,421 @@ +/** + * ### Search plugin + * + * Adds search functionality to jsTree. + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.search', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.search) { return; } + + /** + * stores all defaults for the search plugin + * @name $.jstree.defaults.search + * @plugin search + */ + $.jstree.defaults.search = { + /** + * a jQuery-like AJAX config, which jstree uses if a server should be queried for results. + * + * A `str` (which is the search string) parameter will be added with the request, an optional `inside` parameter will be added if the search is limited to a node id. The expected result is a JSON array with nodes that need to be opened so that matching nodes will be revealed. + * Leave this setting as `false` to not query the server. You can also set this to a function, which will be invoked in the instance's scope and receive 3 parameters - the search string, the callback to call with the array of nodes to load, and the optional node ID to limit the search to + * @name $.jstree.defaults.search.ajax + * @plugin search + */ + ajax : false, + /** + * Indicates if the search should be fuzzy or not (should `chnd3` match `child node 3`). Default is `false`. + * @name $.jstree.defaults.search.fuzzy + * @plugin search + */ + fuzzy : false, + /** + * Indicates if the search should be case sensitive. Default is `false`. + * @name $.jstree.defaults.search.case_sensitive + * @plugin search + */ + case_sensitive : false, + /** + * Indicates if the tree should be filtered (by default) to show only matching nodes (keep in mind this can be a heavy on large trees in old browsers). + * This setting can be changed at runtime when calling the search method. Default is `false`. + * @name $.jstree.defaults.search.show_only_matches + * @plugin search + */ + show_only_matches : false, + /** + * Indicates if the children of matched element are shown (when show_only_matches is true) + * This setting can be changed at runtime when calling the search method. Default is `false`. + * @name $.jstree.defaults.search.show_only_matches_children + * @plugin search + */ + show_only_matches_children : false, + /** + * Indicates if all nodes opened to reveal the search result, should be closed when the search is cleared or a new search is performed. Default is `true`. + * @name $.jstree.defaults.search.close_opened_onclear + * @plugin search + */ + close_opened_onclear : true, + /** + * Indicates if only leaf nodes should be included in search results. Default is `false`. + * @name $.jstree.defaults.search.search_leaves_only + * @plugin search + */ + search_leaves_only : false, + /** + * If set to a function it wil be called in the instance's scope with two arguments - search string and node (where node will be every node in the structure, so use with caution). + * If the function returns a truthy value the node will be considered a match (it might not be displayed if search_only_leaves is set to true and the node is not a leaf). Default is `false`. + * @name $.jstree.defaults.search.search_callback + * @plugin search + */ + search_callback : false + }; + + $.jstree.plugins.search = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this._data.search.str = ""; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.som = false; + this._data.search.smc = false; + this._data.search.hdn = []; + + this.element + .on("search.jstree", $.proxy(function (e, data) { + if(this._data.search.som && data.res.length) { + var m = this._model.data, i, j, p = [], k, l; + for(i = 0, j = data.res.length; i < j; i++) { + if(m[data.res[i]] && !m[data.res[i]].state.hidden) { + p.push(data.res[i]); + p = p.concat(m[data.res[i]].parents); + if(this._data.search.smc) { + for (k = 0, l = m[data.res[i]].children_d.length; k < l; k++) { + if (m[m[data.res[i]].children_d[k]] && !m[m[data.res[i]].children_d[k]].state.hidden) { + p.push(m[data.res[i]].children_d[k]); + } + } + } + } + } + p = $.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root); + this._data.search.hdn = this.hide_all(true); + this.show_node(p, true); + this.redraw(true); + } + }, this)) + .on("clear_search.jstree", $.proxy(function (e, data) { + if(this._data.search.som && data.res.length) { + this.show_node(this._data.search.hdn, true); + this.redraw(true); + } + }, this)); + }; + /** + * used to search the tree nodes for a given string + * @name search(str [, skip_async]) + * @param {String} str the search string + * @param {Boolean} skip_async if set to true server will not be queried even if configured + * @param {Boolean} show_only_matches if set to true only matching nodes will be shown (keep in mind this can be very slow on large trees or old browsers) + * @param {mixed} inside an optional node to whose children to limit the search + * @param {Boolean} append if set to true the results of this search are appended to the previous search + * @plugin search + * @trigger search.jstree + */ + this.search = function (str, skip_async, show_only_matches, inside, append, show_only_matches_children) { + if(str === false || $.trim(str.toString()) === "") { + return this.clear_search(); + } + inside = this.get_node(inside); + inside = inside && inside.id ? inside.id : null; + str = str.toString(); + var s = this.settings.search, + a = s.ajax ? s.ajax : false, + m = this._model.data, + f = null, + r = [], + p = [], i, j; + if(this._data.search.res.length && !append) { + this.clear_search(); + } + if(show_only_matches === undefined) { + show_only_matches = s.show_only_matches; + } + if(show_only_matches_children === undefined) { + show_only_matches_children = s.show_only_matches_children; + } + if(!skip_async && a !== false) { + if($.isFunction(a)) { + return a.call(this, str, $.proxy(function (d) { + if(d && d.d) { d = d.d; } + this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () { + this.search(str, true, show_only_matches, inside, append, show_only_matches_children); + }); + }, this), inside); + } + else { + a = $.extend({}, a); + if(!a.data) { a.data = {}; } + a.data.str = str; + if(inside) { + a.data.inside = inside; + } + if (this._data.search.lastRequest) { + this._data.search.lastRequest.abort(); + } + this._data.search.lastRequest = $.ajax(a) + .fail($.proxy(function () { + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)) + .done($.proxy(function (d) { + if(d && d.d) { d = d.d; } + this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () { + this.search(str, true, show_only_matches, inside, append, show_only_matches_children); + }); + }, this)); + return this._data.search.lastRequest; + } + } + if(!append) { + this._data.search.str = str; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.som = show_only_matches; + this._data.search.smc = show_only_matches_children; + } + + f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy }); + $.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) { + var v = m[i]; + if(v.text && !v.state.hidden && (!s.search_leaves_only || (v.state.loaded && v.children.length === 0)) && ( (s.search_callback && s.search_callback.call(this, str, v)) || (!s.search_callback && f.search(v.text).isMatch) ) ) { + r.push(i); + p = p.concat(v.parents); + } + }); + if(r.length) { + p = $.vakata.array_unique(p); + for(i = 0, j = p.length; i < j; i++) { + if(p[i] !== $.jstree.root && m[p[i]] && this.open_node(p[i], null, 0) === true) { + this._data.search.opn.push(p[i]); + } + } + if(!append) { + this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #'))); + this._data.search.res = r; + } + else { + this._data.search.dom = this._data.search.dom.add($(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); }).join(', #')))); + this._data.search.res = $.vakata.array_unique(this._data.search.res.concat(r)); + } + this._data.search.dom.children(".jstree-anchor").addClass('jstree-search'); + } + /** + * triggered after search is complete + * @event + * @name search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes + * @param {String} str the search string + * @param {Array} res a collection of objects represeing the matching nodes + * @plugin search + */ + this.trigger('search', { nodes : this._data.search.dom, str : str, res : this._data.search.res, show_only_matches : show_only_matches }); + }; + /** + * used to clear the last search (removes classes and shows all nodes if filtering is on) + * @name clear_search() + * @plugin search + * @trigger clear_search.jstree + */ + this.clear_search = function () { + if(this.settings.search.close_opened_onclear) { + this.close_node(this._data.search.opn, 0); + } + /** + * triggered after search is complete + * @event + * @name clear_search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes (the result from the last search) + * @param {String} str the search string (the last search string) + * @param {Array} res a collection of objects represeing the matching nodes (the result from the last search) + * @plugin search + */ + this.trigger('clear_search', { 'nodes' : this._data.search.dom, str : this._data.search.str, res : this._data.search.res }); + if(this._data.search.res.length) { + this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(this._data.search.res, function (v) { + return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&'); + }).join(', #'))); + this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search"); + } + this._data.search.str = ""; + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.dom = $(); + }; + + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + if($.inArray(obj.id, this._data.search.res) !== -1) { + var i, j, tmp = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + tmp.className += ' jstree-search'; + } + } + } + return obj; + }; + }; + + // helpers + (function ($) { + // from http://kiro.me/projects/fuse.html + $.vakata.search = function(pattern, txt, options) { + options = options || {}; + options = $.extend({}, $.vakata.search.defaults, options); + if(options.fuzzy !== false) { + options.fuzzy = true; + } + pattern = options.caseSensitive ? pattern : pattern.toLowerCase(); + var MATCH_LOCATION = options.location, + MATCH_DISTANCE = options.distance, + MATCH_THRESHOLD = options.threshold, + patternLen = pattern.length, + matchmask, pattern_alphabet, match_bitapScore, search; + if(patternLen > 32) { + options.fuzzy = false; + } + if(options.fuzzy) { + matchmask = 1 << (patternLen - 1); + pattern_alphabet = (function () { + var mask = {}, + i = 0; + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] = 0; + } + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] |= 1 << (patternLen - i - 1); + } + return mask; + }()); + match_bitapScore = function (e, x) { + var accuracy = e / patternLen, + proximity = Math.abs(MATCH_LOCATION - x); + if(!MATCH_DISTANCE) { + return proximity ? 1.0 : accuracy; + } + return accuracy + (proximity / MATCH_DISTANCE); + }; + } + search = function (text) { + text = options.caseSensitive ? text : text.toLowerCase(); + if(pattern === text || text.indexOf(pattern) !== -1) { + return { + isMatch: true, + score: 0 + }; + } + if(!options.fuzzy) { + return { + isMatch: false, + score: 1 + }; + } + var i, j, + textLen = text.length, + scoreThreshold = MATCH_THRESHOLD, + bestLoc = text.indexOf(pattern, MATCH_LOCATION), + binMin, binMid, + binMax = patternLen + textLen, + lastRd, start, finish, rd, charMatch, + score = 1, + locations = []; + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + bestLoc = text.lastIndexOf(pattern, MATCH_LOCATION + patternLen); + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + } + } + bestLoc = -1; + for (i = 0; i < patternLen; i++) { + binMin = 0; + binMid = binMax; + while (binMin < binMid) { + if (match_bitapScore(i, MATCH_LOCATION + binMid) <= scoreThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } + binMax = binMid; + start = Math.max(1, MATCH_LOCATION - binMid + 1); + finish = Math.min(MATCH_LOCATION + binMid, textLen) + patternLen; + rd = new Array(finish + 2); + rd[finish + 1] = (1 << i) - 1; + for (j = finish; j >= start; j--) { + charMatch = pattern_alphabet[text.charAt(j - 1)]; + if (i === 0) { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; + } else { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | (((lastRd[j + 1] | lastRd[j]) << 1) | 1) | lastRd[j + 1]; + } + if (rd[j] & matchmask) { + score = match_bitapScore(i, j - 1); + if (score <= scoreThreshold) { + scoreThreshold = score; + bestLoc = j - 1; + locations.push(bestLoc); + if (bestLoc > MATCH_LOCATION) { + start = Math.max(1, 2 * MATCH_LOCATION - bestLoc); + } else { + break; + } + } + } + } + if (match_bitapScore(i + 1, MATCH_LOCATION) > scoreThreshold) { + break; + } + lastRd = rd; + } + return { + isMatch: bestLoc >= 0, + score: score + }; + }; + return txt === true ? { 'search' : search } : search(txt); + }; + $.vakata.search.defaults = { + location : 0, + distance : 100, + threshold : 0.6, + fuzzy : false, + caseSensitive : false + }; + }($)); + + // include the search plugin by default + // $.jstree.defaults.plugins.push("search"); +})); diff --git a/civicrm/bower_components/jstree/src/jstree.sort.js b/civicrm/bower_components/jstree/src/jstree.sort.js new file mode 100644 index 0000000000000000000000000000000000000000..94f8b390145c28403111923951879ae844dbb5c8 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.sort.js @@ -0,0 +1,74 @@ +/** + * ### Sort plugin + * + * Automatically sorts all siblings in the tree according to a sorting function. + */ +/*globals jQuery, define, exports, require */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.sort', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.sort) { return; } + + /** + * the settings function used to sort the nodes. + * It is executed in the tree's context, accepts two nodes as arguments and should return `1` or `-1`. + * @name $.jstree.defaults.sort + * @plugin sort + */ + $.jstree.defaults.sort = function (a, b) { + //return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : this.get_type(a) >= this.get_type(b); + return this.get_text(a) > this.get_text(b) ? 1 : -1; + }; + $.jstree.plugins.sort = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this.element + .on("model.jstree", $.proxy(function (e, data) { + this.sort(data.parent, true); + }, this)) + .on("rename_node.jstree create_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent || data.node.parent, false); + this.redraw_node(data.parent || data.node.parent, true); + }, this)) + .on("move_node.jstree copy_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent, false); + this.redraw_node(data.parent, true); + }, this)); + }; + /** + * used to sort a node's children + * @private + * @name sort(obj [, deep]) + * @param {mixed} obj the node + * @param {Boolean} deep if set to `true` nodes are sorted recursively. + * @plugin sort + * @trigger search.jstree + */ + this.sort = function (obj, deep) { + var i, j; + obj = this.get_node(obj); + if(obj && obj.children && obj.children.length) { + obj.children.sort($.proxy(this.settings.sort, this)); + if(deep) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + this.sort(obj.children_d[i], false); + } + } + } + }; + }; + + // include the sort plugin by default + // $.jstree.defaults.plugins.push("sort"); +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.state.js b/civicrm/bower_components/jstree/src/jstree.state.js new file mode 100644 index 0000000000000000000000000000000000000000..f87cf4fb642d6171404dfe9e575488988122a68c --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.state.js @@ -0,0 +1,125 @@ +/** + * ### State plugin + * + * Saves the state of the tree (selected nodes, opened nodes) on the user's computer using available options (localStorage, cookies, etc) + */ +/*globals jQuery, define, exports, require */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.state', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.state) { return; } + + var to = false; + /** + * stores all defaults for the state plugin + * @name $.jstree.defaults.state + * @plugin state + */ + $.jstree.defaults.state = { + /** + * A string for the key to use when saving the current tree (change if using multiple trees in your project). Defaults to `jstree`. + * @name $.jstree.defaults.state.key + * @plugin state + */ + key : 'jstree', + /** + * A space separated list of events that trigger a state save. Defaults to `changed.jstree open_node.jstree close_node.jstree`. + * @name $.jstree.defaults.state.events + * @plugin state + */ + events : 'changed.jstree open_node.jstree close_node.jstree check_node.jstree uncheck_node.jstree', + /** + * Time in milliseconds after which the state will expire. Defaults to 'false' meaning - no expire. + * @name $.jstree.defaults.state.ttl + * @plugin state + */ + ttl : false, + /** + * A function that will be executed prior to restoring state with one argument - the state object. Can be used to clear unwanted parts of the state. + * @name $.jstree.defaults.state.filter + * @plugin state + */ + filter : false + }; + $.jstree.plugins.state = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + var bind = $.proxy(function () { + this.element.on(this.settings.state.events, $.proxy(function () { + if(to) { clearTimeout(to); } + to = setTimeout($.proxy(function () { this.save_state(); }, this), 100); + }, this)); + /** + * triggered when the state plugin is finished restoring the state (and immediately after ready if there is no state to restore). + * @event + * @name state_ready.jstree + * @plugin state + */ + this.trigger('state_ready'); + }, this); + this.element + .on("ready.jstree", $.proxy(function (e, data) { + this.element.one("restore_state.jstree", bind); + if(!this.restore_state()) { bind(); } + }, this)); + }; + /** + * save the state + * @name save_state() + * @plugin state + */ + this.save_state = function () { + var st = { 'state' : this.get_state(), 'ttl' : this.settings.state.ttl, 'sec' : +(new Date()) }; + $.vakata.storage.set(this.settings.state.key, JSON.stringify(st)); + }; + /** + * restore the state from the user's computer + * @name restore_state() + * @plugin state + */ + this.restore_state = function () { + var k = $.vakata.storage.get(this.settings.state.key); + if(!!k) { try { k = JSON.parse(k); } catch(ex) { return false; } } + if(!!k && k.ttl && k.sec && +(new Date()) - k.sec > k.ttl) { return false; } + if(!!k && k.state) { k = k.state; } + if(!!k && $.isFunction(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); } + if(!!k) { + this.element.one("set_state.jstree", function (e, data) { data.instance.trigger('restore_state', { 'state' : $.extend(true, {}, k) }); }); + this.set_state(k); + return true; + } + return false; + }; + /** + * clear the state on the user's computer + * @name clear_state() + * @plugin state + */ + this.clear_state = function () { + return $.vakata.storage.del(this.settings.state.key); + }; + }; + + (function ($, undefined) { + $.vakata.storage = { + // simply specifying the functions in FF throws an error + set : function (key, val) { return window.localStorage.setItem(key, val); }, + get : function (key) { return window.localStorage.getItem(key); }, + del : function (key) { return window.localStorage.removeItem(key); } + }; + }($)); + + // include the state plugin by default + // $.jstree.defaults.plugins.push("state"); +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/jstree.types.js b/civicrm/bower_components/jstree/src/jstree.types.js new file mode 100644 index 0000000000000000000000000000000000000000..706829a9d07aedbfa41c487102fd742e36f96a80 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.types.js @@ -0,0 +1,372 @@ +/** + * ### Types plugin + * + * Makes it possible to add predefined types for groups of nodes, which make it possible to easily control nesting rules and icon for each group. + */ +/*globals jQuery, define, exports, require */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.types', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.types) { return; } + + /** + * An object storing all types as key value pairs, where the key is the type name and the value is an object that could contain following keys (all optional). + * + * * `max_children` the maximum number of immediate children this node type can have. Do not specify or set to `-1` for unlimited. + * * `max_depth` the maximum number of nesting this node type can have. A value of `1` would mean that the node can have children, but no grandchildren. Do not specify or set to `-1` for unlimited. + * * `valid_children` an array of node type strings, that nodes of this type can have as children. Do not specify or set to `-1` for no limits. + * * `icon` a string - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class. Omit to use the default icon from your theme. + * * `li_attr` an object of values which will be used to add HTML attributes on the resulting LI DOM node (merged with the node's own data) + * * `a_attr` an object of values which will be used to add HTML attributes on the resulting A DOM node (merged with the node's own data) + * + * There are two predefined types: + * + * * `#` represents the root of the tree, for example `max_children` would control the maximum number of root nodes. + * * `default` represents the default node - any settings here will be applied to all nodes that do not have a type specified. + * + * @name $.jstree.defaults.types + * @plugin types + */ + $.jstree.defaults.types = { + 'default' : {} + }; + $.jstree.defaults.types[$.jstree.root] = {}; + + $.jstree.plugins.types = function (options, parent) { + this.init = function (el, options) { + var i, j; + if(options && options.types && options.types['default']) { + for(i in options.types) { + if(i !== "default" && i !== $.jstree.root && options.types.hasOwnProperty(i)) { + for(j in options.types['default']) { + if(options.types['default'].hasOwnProperty(j) && options.types[i][j] === undefined) { + options.types[i][j] = options.types['default'][j]; + } + } + } + } + } + parent.init.call(this, el, options); + this._model.data[$.jstree.root].type = $.jstree.root; + }; + this.refresh = function (skip_loading, forget_state) { + parent.refresh.call(this, skip_loading, forget_state); + this._model.data[$.jstree.root].type = $.jstree.root; + }; + this.bind = function () { + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + dpc = data.nodes, + t = this.settings.types, + i, j, c = 'default', k; + for(i = 0, j = dpc.length; i < j; i++) { + c = 'default'; + if(m[dpc[i]].original && m[dpc[i]].original.type && t[m[dpc[i]].original.type]) { + c = m[dpc[i]].original.type; + } + if(m[dpc[i]].data && m[dpc[i]].data.jstree && m[dpc[i]].data.jstree.type && t[m[dpc[i]].data.jstree.type]) { + c = m[dpc[i]].data.jstree.type; + } + m[dpc[i]].type = c; + if(m[dpc[i]].icon === true && t[c].icon !== undefined) { + m[dpc[i]].icon = t[c].icon; + } + if(t[c].li_attr !== undefined && typeof t[c].li_attr === 'object') { + for (k in t[c].li_attr) { + if (t[c].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[dpc[i]].li_attr[k] === undefined) { + m[dpc[i]].li_attr[k] = t[c].li_attr[k]; + } + else if (k === 'class') { + m[dpc[i]].li_attr['class'] = t[c].li_attr['class'] + ' ' + m[dpc[i]].li_attr['class']; + } + } + } + } + if(t[c].a_attr !== undefined && typeof t[c].a_attr === 'object') { + for (k in t[c].a_attr) { + if (t[c].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[dpc[i]].a_attr[k] === undefined) { + m[dpc[i]].a_attr[k] = t[c].a_attr[k]; + } + else if (k === 'href' && m[dpc[i]].a_attr[k] === '#') { + m[dpc[i]].a_attr['href'] = t[c].a_attr['href']; + } + else if (k === 'class') { + m[dpc[i]].a_attr['class'] = t[c].a_attr['class'] + ' ' + m[dpc[i]].a_attr['class']; + } + } + } + } + } + m[$.jstree.root].type = $.jstree.root; + }, this)); + parent.bind.call(this); + }; + this.get_json = function (obj, options, flat) { + var i, j, + m = this._model.data, + opt = options ? $.extend(true, {}, options, {no_id:false}) : {}, + tmp = parent.get_json.call(this, obj, opt, flat); + if(tmp === false) { return false; } + if($.isArray(tmp)) { + for(i = 0, j = tmp.length; i < j; i++) { + tmp[i].type = tmp[i].id && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default"; + if(options && options.no_id) { + delete tmp[i].id; + if(tmp[i].li_attr && tmp[i].li_attr.id) { + delete tmp[i].li_attr.id; + } + if(tmp[i].a_attr && tmp[i].a_attr.id) { + delete tmp[i].a_attr.id; + } + } + } + } + else { + tmp.type = tmp.id && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default"; + if(options && options.no_id) { + tmp = this._delete_ids(tmp); + } + } + return tmp; + }; + this._delete_ids = function (tmp) { + if($.isArray(tmp)) { + for(var i = 0, j = tmp.length; i < j; i++) { + tmp[i] = this._delete_ids(tmp[i]); + } + return tmp; + } + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + if(tmp.a_attr && tmp.a_attr.id) { + delete tmp.a_attr.id; + } + if(tmp.children && $.isArray(tmp.children)) { + tmp.children = this._delete_ids(tmp.children); + } + return tmp; + }; + this.check = function (chk, obj, par, pos, more) { + if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var m = obj && obj.id ? (more && more.origin ? more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j; + m = m && m._model && m._model.data ? m._model.data : null; + switch(chk) { + case "create_node": + case "move_node": + case "copy_node": + if(chk !== 'move_node' || $.inArray(obj.id, par.children) === -1) { + tmp = this.get_rules(par); + if(tmp.max_children !== undefined && tmp.max_children !== -1 && tmp.max_children === par.children.length) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(tmp.valid_children !== undefined && tmp.valid_children !== -1 && $.inArray((obj.type || 'default'), tmp.valid_children) === -1) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(m && obj.children_d && obj.parents) { + d = 0; + for(i = 0, j = obj.children_d.length; i < j; i++) { + d = Math.max(d, m[obj.children_d[i]].parents.length); + } + d = d - obj.parents.length + 1; + } + if(d <= 0 || d === undefined) { d = 1; } + do { + if(tmp.max_depth !== undefined && tmp.max_depth !== -1 && tmp.max_depth < d) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + par = this.get_node(par.parent); + tmp = this.get_rules(par); + d++; + } while(par); + } + break; + } + return true; + }; + /** + * used to retrieve the type settings object for a node + * @name get_rules(obj) + * @param {mixed} obj the node to find the rules for + * @return {Object} + * @plugin types + */ + this.get_rules = function (obj) { + obj = this.get_node(obj); + if(!obj) { return false; } + var tmp = this.get_type(obj, true); + if(tmp.max_depth === undefined) { tmp.max_depth = -1; } + if(tmp.max_children === undefined) { tmp.max_children = -1; } + if(tmp.valid_children === undefined) { tmp.valid_children = -1; } + return tmp; + }; + /** + * used to retrieve the type string or settings object for a node + * @name get_type(obj [, rules]) + * @param {mixed} obj the node to find the rules for + * @param {Boolean} rules if set to `true` instead of a string the settings object will be returned + * @return {String|Object} + * @plugin types + */ + this.get_type = function (obj, rules) { + obj = this.get_node(obj); + return (!obj) ? false : ( rules ? $.extend({ 'type' : obj.type }, this.settings.types[obj.type]) : obj.type); + }; + /** + * used to change a node's type + * @name set_type(obj, type) + * @param {mixed} obj the node to change + * @param {String} type the new type + * @plugin types + */ + this.set_type = function (obj, type) { + var m = this._model.data, t, t1, t2, old_type, old_icon, k, d, a; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_type(obj[t1], type); + } + return true; + } + t = this.settings.types; + obj = this.get_node(obj); + if(!t[type] || !obj) { return false; } + d = this.get_node(obj, true); + if (d && d.length) { + a = d.children('.jstree-anchor'); + } + old_type = obj.type; + old_icon = this.get_icon(obj); + obj.type = type; + if(old_icon === true || !t[old_type] || (t[old_type].icon !== undefined && old_icon === t[old_type].icon)) { + this.set_icon(obj, t[type].icon !== undefined ? t[type].icon : true); + } + + // remove old type props + if(t[old_type] && t[old_type].li_attr !== undefined && typeof t[old_type].li_attr === 'object') { + for (k in t[old_type].li_attr) { + if (t[old_type].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (k === 'class') { + m[obj.id].li_attr['class'] = (m[obj.id].li_attr['class'] || '').replace(t[old_type].li_attr[k], ''); + if (d) { d.removeClass(t[old_type].li_attr[k]); } + } + else if (m[obj.id].li_attr[k] === t[old_type].li_attr[k]) { + m[obj.id].li_attr[k] = null; + if (d) { d.removeAttr(k); } + } + } + } + } + if(t[old_type] && t[old_type].a_attr !== undefined && typeof t[old_type].a_attr === 'object') { + for (k in t[old_type].a_attr) { + if (t[old_type].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (k === 'class') { + m[obj.id].a_attr['class'] = (m[obj.id].a_attr['class'] || '').replace(t[old_type].a_attr[k], ''); + if (a) { a.removeClass(t[old_type].a_attr[k]); } + } + else if (m[obj.id].a_attr[k] === t[old_type].a_attr[k]) { + if (k === 'href') { + m[obj.id].a_attr[k] = '#'; + if (a) { a.attr('href', '#'); } + } + else { + delete m[obj.id].a_attr[k]; + if (a) { a.removeAttr(k); } + } + } + } + } + } + + // add new props + if(t[type].li_attr !== undefined && typeof t[type].li_attr === 'object') { + for (k in t[type].li_attr) { + if (t[type].li_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[obj.id].li_attr[k] === undefined) { + m[obj.id].li_attr[k] = t[type].li_attr[k]; + if (d) { + if (k === 'class') { + d.addClass(t[type].li_attr[k]); + } + else { + d.attr(k, t[type].li_attr[k]); + } + } + } + else if (k === 'class') { + m[obj.id].li_attr['class'] = t[type].li_attr[k] + ' ' + m[obj.id].li_attr['class']; + if (d) { d.addClass(t[type].li_attr[k]); } + } + } + } + } + if(t[type].a_attr !== undefined && typeof t[type].a_attr === 'object') { + for (k in t[type].a_attr) { + if (t[type].a_attr.hasOwnProperty(k)) { + if (k === 'id') { + continue; + } + else if (m[obj.id].a_attr[k] === undefined) { + m[obj.id].a_attr[k] = t[type].a_attr[k]; + if (a) { + if (k === 'class') { + a.addClass(t[type].a_attr[k]); + } + else { + a.attr(k, t[type].a_attr[k]); + } + } + } + else if (k === 'href' && m[obj.id].a_attr[k] === '#') { + m[obj.id].a_attr['href'] = t[type].a_attr['href']; + if (a) { a.attr('href', t[type].a_attr['href']); } + } + else if (k === 'class') { + m[obj.id].a_attr['class'] = t[type].a_attr['class'] + ' ' + m[obj.id].a_attr['class']; + if (a) { a.addClass(t[type].a_attr[k]); } + } + } + } + } + + return true; + }; + }; + // include the types plugin by default + // $.jstree.defaults.plugins.push("types"); +})); diff --git a/civicrm/bower_components/jstree/src/jstree.unique.js b/civicrm/bower_components/jstree/src/jstree.unique.js new file mode 100644 index 0000000000000000000000000000000000000000..bfe2f1b8f85b7df5e86a86fc81f14c1e43ae538b --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.unique.js @@ -0,0 +1,121 @@ +/** + * ### Unique plugin + * + * Enforces that no nodes with the same name can coexist as siblings. + */ +/*globals jQuery, define, exports, require */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.unique', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.unique) { return; } + + /** + * stores all defaults for the unique plugin + * @name $.jstree.defaults.unique + * @plugin unique + */ + $.jstree.defaults.unique = { + /** + * Indicates if the comparison should be case sensitive. Default is `false`. + * @name $.jstree.defaults.unique.case_sensitive + * @plugin unique + */ + case_sensitive : false, + /** + * A callback executed in the instance's scope when a new node is created and the name is already taken, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`. + * @name $.jstree.defaults.unique.duplicate + * @plugin unique + */ + duplicate : function (name, counter) { + return name + ' (' + counter + ')'; + } + }; + + $.jstree.plugins.unique = function (options, parent) { + this.check = function (chk, obj, par, pos, more) { + if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + if(!par || !par.children) { return true; } + var n = chk === "rename_node" ? pos : obj.text, + c = [], + s = this.settings.unique.case_sensitive, + m = this._model.data, i, j; + for(i = 0, j = par.children.length; i < j; i++) { + c.push(s ? m[par.children[i]].text : m[par.children[i]].text.toLowerCase()); + } + if(!s) { n = n.toLowerCase(); } + switch(chk) { + case "delete_node": + return true; + case "rename_node": + i = ($.inArray(n, c) === -1 || (obj.text && obj.text[ s ? 'toString' : 'toLowerCase']() === n)); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "create_node": + i = ($.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "copy_node": + i = ($.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "move_node": + i = ( (obj.parent === par.id && (!more || !more.is_multi)) || $.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + } + return true; + }; + this.create_node = function (par, node, pos, callback, is_loaded) { + if(!node || node.text === undefined) { + if(par === null) { + par = $.jstree.root; + } + par = this.get_node(par); + if(!par) { + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + } + pos = pos === undefined ? "last" : pos; + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + } + if(!node) { node = {}; } + var tmp, n, dpc, i, j, m = this._model.data, s = this.settings.unique.case_sensitive, cb = this.settings.unique.duplicate; + n = tmp = this.get_string('New node'); + dpc = []; + for(i = 0, j = par.children.length; i < j; i++) { + dpc.push(s ? m[par.children[i]].text : m[par.children[i]].text.toLowerCase()); + } + i = 1; + while($.inArray(s ? n : n.toLowerCase(), dpc) !== -1) { + n = cb.call(this, tmp, (++i)).toString(); + } + node.text = n; + } + return parent.create_node.call(this, par, node, pos, callback, is_loaded); + }; + }; + + // include the unique plugin by default + // $.jstree.defaults.plugins.push("unique"); +})); diff --git a/civicrm/bower_components/jstree/src/jstree.wholerow.js b/civicrm/bower_components/jstree/src/jstree.wholerow.js new file mode 100644 index 0000000000000000000000000000000000000000..e8fe3e6d54f062030d555da5177475d481a61852 --- /dev/null +++ b/civicrm/bower_components/jstree/src/jstree.wholerow.js @@ -0,0 +1,122 @@ +/** + * ### Wholerow plugin + * + * Makes each node appear block level. Making selection easier. May cause slow down for large trees in old browsers. + */ +/*globals jQuery, define, exports, require */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.wholerow', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.wholerow) { return; } + + var div = document.createElement('DIV'); + div.setAttribute('unselectable','on'); + div.setAttribute('role','presentation'); + div.className = 'jstree-wholerow'; + div.innerHTML = ' '; + $.jstree.plugins.wholerow = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this.element + .on('ready.jstree set_state.jstree', $.proxy(function () { + this.hide_dots(); + }, this)) + .on("init.jstree loading.jstree ready.jstree", $.proxy(function () { + //div.style.height = this._data.core.li_height + 'px'; + this.get_container_ul().addClass('jstree-wholerow-ul'); + }, this)) + .on("deselect_all.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + }, this)) + .on("changed.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + var tmp = false, i, j; + for(i = 0, j = data.selected.length; i < j; i++) { + tmp = this.get_node(data.selected[i], true); + if(tmp && tmp.length) { + tmp.children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + } + } + }, this)) + .on("open_node.jstree", $.proxy(function (e, data) { + this.get_node(data.node, true).find('.jstree-clicked').parent().children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + }, this)) + .on("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) { + if(e.type === "hover_node" && this.is_disabled(data.node)) { return; } + this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered'); + }, this)) + .on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) { + if (this._data.contextmenu) { + e.preventDefault(); + var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp); + } + }, this)) + /*! + .on("mousedown.jstree touchstart.jstree", ".jstree-wholerow", function (e) { + if(e.target === e.currentTarget) { + var a = $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor"); + e.target = a[0]; + a.trigger(e); + } + }) + */ + .on("click.jstree", ".jstree-wholerow", function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }) + .on("dblclick.jstree", ".jstree-wholerow", function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('dblclick', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }) + .on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus(); + }, this)) + .on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", $.proxy(function (e) { + e.stopImmediatePropagation(); + if(!this.is_disabled(e.currentTarget)) { + this.hover_node(e.currentTarget); + } + return false; + }, this)) + .on("mouseleave.jstree", ".jstree-node", $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }; + this.teardown = function () { + if(this.settings.wholerow) { + this.element.find(".jstree-wholerow").remove(); + } + parent.teardown.call(this); + }; + this.redraw_node = function(obj, deep, callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + var tmp = div.cloneNode(true); + //tmp.style.height = this._data.core.li_height + 'px'; + if($.inArray(obj.id, this._data.core.selected) !== -1) { tmp.className += ' jstree-wholerow-clicked'; } + if(this._data.core.focused && this._data.core.focused === obj.id) { tmp.className += ' jstree-wholerow-hovered'; } + obj.insertBefore(tmp, obj.childNodes[0]); + } + return obj; + }; + }; + // include the wholerow plugin by default + // $.jstree.defaults.plugins.push("wholerow"); +})); diff --git a/civicrm/bower_components/jstree/src/misc.js b/civicrm/bower_components/jstree/src/misc.js new file mode 100644 index 0000000000000000000000000000000000000000..d2d789b1f3a766c1308f4ca17f4b02ebaa145873 --- /dev/null +++ b/civicrm/bower_components/jstree/src/misc.js @@ -0,0 +1,601 @@ +/* global jQuery */ + +// disable all events +(function ($, undefined) { + "use strict"; + $.jstree.plugins.trigger = function (options, parent) { + this.init = function (el, options) { + // do not forget parent + parent.init.call(this, el, options); + this._data.trigger.disabled = false; + }; + this.trigger = function (ev, data) { + if(!this._data.trigger.disabled) { + parent.trigger.call(this, ev, data); + } + }; + this.disable_events = function () { this._data.trigger.disabled = true; }; + this.enable_events = function () { this._data.trigger.disabled = false; }; + }; +})(jQuery); + +// mapping +(function ($, undefined) { + "use strict"; + // use this if you need any options + $.jstree.defaults.mapper = { + option_key : "option_value" + }; + $.jstree.plugins.mapper = function () { + this._parse_model_from_json = function (d, p, ps) { + // d is the node from the server, it will be called recursively for children, + // so you do not need to process at once + /* // for example + for(var i in d) { + if(d.hasOwnProperty(i)) { + d[i.toLowerCase()] = d[i]; + } + } + */ + return parent._parse_model_from_json.call(this, d, p, ps); + }; + }; +})(jQuery); + +// no hover +(function ($, undefined) { + "use strict"; + $.jstree.plugins.nohover = function () { + this.hover_node = $.noop; + }; +})(jQuery); + +// force multiple select +(function ($, undefined) { + "use strict"; + $.jstree.defaults.multiselect = {}; + $.jstree.plugins.multiselect = function (options, parent) { + this.activate_node = function (obj, e) { + e.ctrlKey = true; + parent.activate_node.call(this, obj, e); + }; + }; +})(jQuery); + +// real checkboxes +(function ($, undefined) { + "use strict"; + + var inp = document.createElement("INPUT"); + inp.type = "checkbox"; + inp.className = "jstree-checkbox jstree-realcheckbox"; + + $.jstree.defaults.realcheckboxes = {}; + + $.jstree.plugins.realcheckboxes = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this._data.realcheckboxes.uto = false; + this.element + .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree ready.jstree loaded.jstree', $.proxy(function () { + // only if undetermined is in setting + if(this._data.realcheckboxes.uto) { clearTimeout(this._data.realcheckboxes.uto); } + this._data.realcheckboxes.uto = setTimeout($.proxy(this._realcheckboxes, this), 50); + }, this)); + }; + this.redraw_node = function(obj, deep, callback, force_draw) { + obj = parent.redraw_node.call(this, obj, deep, callback, force_draw); + if(obj) { + var i, j, tmp = null, chk = inp.cloneNode(true); + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + for(i = 0, j = tmp.childNodes.length; i < j; i++) { + if(tmp.childNodes[i] && tmp.childNodes[i].className && tmp.childNodes[i].className.indexOf("jstree-checkbox") !== -1) { + tmp = tmp.childNodes[i]; + break; + } + } + } + if(tmp && tmp.tagName === "I") { + tmp.style.backgroundColor = "transparent"; + tmp.style.backgroundImage = "none"; + tmp.appendChild(chk); + } + } + return obj; + }; + this._realcheckboxes = function () { + var ts = this.settings.checkbox.tie_selection; + console.log(ts); + $('.jstree-realcheckbox').each(function () { + this.checked = (!ts && this.parentNode.parentNode.className.indexOf("jstree-checked") !== -1) || (ts && this.parentNode.parentNode.className.indexOf('jstree-clicked') !== -1); + this.indeterminate = this.parentNode.className.indexOf("jstree-undetermined") !== -1; + this.disabled = this.parentNode.parentNode.className.indexOf("disabled") !== -1; + }); + }; + }; +})(jQuery); + +// no state +(function ($, undefined) { + "use strict"; + $.jstree.plugins.nostate = function () { + this.set_state = function (state, callback) { + if(callback) { callback.call(this); } + this.trigger('set_state'); + }; + }; +})(jQuery); + +// no selected in state +(function ($, undefined) { + "use strict"; + $.jstree.plugins.noselectedstate = function (options, parent) { + this.get_state = function () { + var state = parent.get_state.call(this); + delete state.core.selected; + return state; + }; + }; +})(jQuery); + +// additional icon on node (outside of anchor) +(function ($, undefined) { + "use strict"; + var img = document.createElement('IMG'); + //img.src = "http://www.dpcd.vic.gov.au/__data/assets/image/0004/30667/help.gif"; + img.className = "jstree-questionmark"; + + $.jstree.defaults.questionmark = $.noop; + $.jstree.plugins.questionmark = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this.element + .on("click.jstree", ".jstree-questionmark", $.proxy(function (e) { + e.stopImmediatePropagation(); + this.settings.questionmark.call(this, this.get_node(e.target)); + }, this)); + }; + this.teardown = function () { + if(this.settings.questionmark) { + this.element.find(".jstree-questionmark").remove(); + } + parent.teardown.call(this); + }; + this.redraw_node = function(obj, deep, callback, force_draw) { + obj = parent.redraw_node.call(this, obj, deep, callback, force_draw); + if(obj) { + var tmp = img.cloneNode(true); + obj.insertBefore(tmp, obj.childNodes[2]); + } + return obj; + }; + }; +})(jQuery); + +// auto numbering +(function ($, undefined) { + "use strict"; + var span = document.createElement('SPAN'); + span.className = "jstree-numbering"; + + $.jstree.defaults.numbering = {}; + $.jstree.plugins.numbering = function (options, parent) { + this.teardown = function () { + if(this.settings.questionmark) { + this.element.find(".jstree-numbering").remove(); + } + parent.teardown.call(this); + }; + this.get_number = function (obj) { + obj = this.get_node(obj); + var ind = $.inArray(obj.id, this.get_node(obj.parent).children) + 1; + return obj.parent === '#' ? ind : this.get_number(obj.parent) + '.' + ind; + }; + this.redraw_node = function(obj, deep, callback, force_draw) { + var i, j, tmp = null, elm = null, org = this.get_number(obj); + obj = parent.redraw_node.call(this, obj, deep, callback, force_draw); + if(obj) { + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + elm = span.cloneNode(true); + elm.innerHTML = org + '. '; + tmp.insertBefore(elm, tmp.childNodes[tmp.childNodes.length - 1]); + } + } + return obj; + }; + }; +})(jQuery); + +// additional icon on node (inside anchor) +(function ($, undefined) { + "use strict"; + var _s = document.createElement('SPAN'); + _s.className = 'fa-stack jstree-stackedicon'; + var _i = document.createElement('I'); + _i.className = 'jstree-icon'; + _i.setAttribute('role', 'presentation'); + + $.jstree.plugins.stackedicon = function (options, parent) { + this.teardown = function () { + this.element.find(".jstree-stackedicon").remove(); + parent.teardown.call(this); + }; + this.redraw_node = function(obj, deep, is_callback, force_render) { + obj = parent.redraw_node.apply(this, arguments); + if(obj) { + var i, j, tmp = null, icon = null, temp = null; + for(i = 0, j = obj.childNodes.length; i < j; i++) { + if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) { + tmp = obj.childNodes[i]; + break; + } + } + if(tmp) { + if(this._model.data[obj.id].state.icons && this._model.data[obj.id].state.icons.length) { + icon = _s.cloneNode(false); + for(i = 0, j = this._model.data[obj.id].state.icons.length; i < j; i++) { + temp = _i.cloneNode(false); + temp.className += ' ' + this._model.data[obj.id].state.icons[i]; + icon.appendChild(temp); + } + tmp.insertBefore(icon, tmp.childNodes[0]); + } + } + } + return obj; + }; + }; +})(jQuery); + +// selecting a node opens it +(function ($, undefined) { + "use strict"; + $.jstree.plugins.selectopens = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this.element.on('select_node.jstree', function (e, data) { data.instance.open_node(data.node); }); + }; + }; +})(jQuery); + +// object as data +(function ($, undefined) { + "use strict"; + $.jstree.defaults.datamodel = {}; + $.jstree.plugins.datamodel = function (options, parent) { + this.init = function (el, options) { + this._data.datamodel = {}; + parent.init.call(this, el, options); + }; + this._datamodel = function (id, nodes, callback) { + var i = 0, j = nodes.length, tmp = [], obj = null; + for(; i < j; i++) { + this._data.datamodel[nodes[i].getID()] = nodes[i]; + obj = { + id : nodes[i].getID(), + text : nodes[i].getText(), + children : nodes[i].hasChildren() + }; + if(nodes[i].getExtra) { + obj = nodes[i].getExtra(obj); // icon, type + } + tmp.push(obj); + } + return this._append_json_data(id, tmp, $.proxy(function (status) { + callback.call(this, status); + }, this)); + }; + this._load_node = function (obj, callback) { + var id = obj.id; + var nd = obj.id === "#" ? this.settings.core.data : this._data.datamodel[obj.id].getChildren($.proxy(function (nodes) { + this._datamodel(id, nodes, callback); + }, this)); + if($.isArray(nd)) { + this._datamodel(id, nd, callback); + } + }; + }; +})(jQuery); +/* + demo of the above + function treeNode(val) { + var id = ++treeNode.counter; + this.getID = function () { + return id; + }; + this.getText = function () { + return val.toString(); + }; + this.getExtra = function (obj) { + obj.icon = false; + return obj; + }; + this.hasChildren = function () { + return true; + }; + this.getChildren = function () { + return [ + new treeNode(Math.pow(val, 2)), + new treeNode(Math.sqrt(val)), + ]; + }; + } + treeNode.counter = 0; + + $('#jstree').jstree({ + 'core': { + 'data': [ + new treeNode(2), + new treeNode(3), + new treeNode(4), + new treeNode(5) + ] + }, + plugins : ['datamodel'] + }); +*/ + +// untested sample plugin to keep all nodes in the DOM +(function ($, undefined) { + "use strict"; + $.jstree.plugins.dom = function (options, parent) { + this.redraw_node = function (node, deep, is_callback, force_render) { + return parent.redraw_node.call(this, node, deep, is_callback, true); + }; + this.close_node = function (obj, animation) { + var t1, t2, t, d; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.close_node(obj[t1], animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === $.jstree.root) { + return false; + } + if(this.is_closed(obj)) { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + t = this; + d = this.get_node(obj, true); + if(d.length) { + if(!animation) { + d[0].className = d[0].className.replace('jstree-open', 'jstree-closed'); + d.attr("aria-expanded", false); + } + else { + d + .children(".jstree-children").attr("style","display:block !important").end() + .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false) + .children(".jstree-children").stop(true, true).slideUp(animation, function () { + this.style.display = ""; + t.trigger("after_close", { "node" : obj }); + }); + } + } + obj.state.opened = false; + this.trigger('close_node',{ "node" : obj }); + if(!animation || !d.length) { + this.trigger("after_close", { "node" : obj }); + } + }; + }; +})(jQuery); + +// customize plugin by @Lusito +// https://github.com/Lusito/jstree/blob/node-customize/src/jstree-node-customize.js +/** + * ### Node Customize plugin + * + * Allows to customize nodes when they are drawn. + */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.node_customize', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.node_customize) { return; } + + /** + * the settings object. + * key is the attribute name to select the customizer function from switch. + * switch is a key => function(el, node) map. + * default: function(el, node) will be called if the type could not be mapped + * @name $.jstree.defaults.node_customize + * @plugin node_customize + */ + $.jstree.defaults.node_customize = { + "key": "type", + "switch": {}, + "default": null + }; + + $.jstree.plugins.node_customize = function (options, parent) { + this.redraw_node = function (obj, deep, callback, force_draw) { + var node_id = obj; + var el = parent.redraw_node.apply(this, arguments); + if (el) { + var node = this._model.data[node_id]; + var cfg = this.settings.node_customize; + var key = cfg.key; + var type = (node && node.original && node.original[key]); + var customizer = (type && cfg.switch[type]) || cfg.default; + if(customizer) + customizer(el, node); + } + return el; + }; + } +})); + + +// parentsload plugin by @ashl1 +/** + * ### Parentsload plugin + * + * Change load_node() functionality in jsTree, to possible load not yes downloaded node with all it parent in a single request (only useful with lazy loading). + * + * version 1.0.0 (Alexey Shildyakov - ashl1future@gmail.com) + * 2015: Compatible with jsTree-3.2.1 + */ +/*globals jQuery, define, exports, require, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.parentsload', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery, jQuery.jstree); + } +}(function ($, jstree, undefined) { + "use strict"; + + if($.jstree.plugins.parentsload) { return; } + + /** + * parentsload configuration + * + * The configuration syntax is almost the same as for core.data option. You must set parenstload.data the following: + * + * parentsload: { + * data: function(){} // this function overwrites core data.data options + * } + * + * OR + * + * parentsload: { + * data: { + * url: function(node){} OR string, + * data: function(node){} OR associative array as json{data} jQuery parameter + * } + * } + * + * In last case at least on of 'url' or 'data' must be presented. + * + * At first, the plugin load_node() detects if the node already downloaded. If is - uses the core.data settings, if not - uses parentsload.data settings + * to fetch in one query the specified node and all its parent. The data must be in the first mentioned JSON format with set nested children[]. + * Each node level should consist of all nodes on the level to properly work with the tree in the future. Otherwise, you must manually call load_node + * on every parent node to fetch all children nodes on that level. + * + * @name $.jstree.defaults.parentsload + * @plugin parentsload + */ + $.jstree.defaults.parentsload = null; + $.jstree.plugins.parentsload = function (options, parent) { + this.init = function (el, options) { + parent.init.call(this, el, options); + this.patch_data() + }; + this.patch_data = function(){ + var parentsloadSettings = this.settings.parentsload; + var jsTreeDataSettings = this.settings.core.data; + var self = this; + + var callError = function(number, message) { + self._data.core.last_error = { 'error' : 'configuration', 'plugin' : 'parentsload', 'id' : 'parentsload_' + number, 'reason' : message, 'data' : JSON.stringify({config: parentsloadSettings}) }; + self.settings.core.error.call(self, self._data.core.last_error); + } + + if(!parentsloadSettings) { + callError('01', 'The configuration must be presented') + return + } + parentsloadSettings = parentsloadSettings.data; + + var patchSettingsProperty = function (propertyName) { + var property = parentsloadSettings[propertyName], + coreProperty = jsTreeDataSettings[propertyName]; + if (property) { + jsTreeDataSettings[propertyName] = function(node) { + if (this.get_node(node).parentsload_required) { + if ($.isFunction(property)) { + return property.call(this, node) + } else {// (typeof property === 'string') + return property + } + } else { + if ($.isFunction(coreProperty)) { + return coreProperty.call(this, node) + } else { // (typeof coreProperty === 'string') + return coreProperty + } + } + } + } /* else { + use jstree the same data[propertyName] settings + }*/ + } + + if($.isFunction(parentsloadSettings)) { + this.settings.data = parentsloadSettings + } else if (typeof parentsloadSettings === 'object') { + if (! (parentsloadSettings.url || parentsloadSettings.data)) { + callError('02', 'The "data.url" or "data.data" must be presented in configuration') + return + } + patchSettingsProperty('url') + patchSettingsProperty('data') + + } else { + callError('03', 'The appropriate "data.url" or "data.data" must be presented in configuration') + } + } + + this.load_node = function (obj, callback) { + if($.isArray(obj)) { + // FIXME: _load_nodes will not load nodes not presented in the tree + this._load_nodes(obj.slice(), callback); + return true; + } + var foundObj = this.get_node(obj); + if (foundObj) { + return parent.load_node.apply(this, arguments) + } else { + // node hasn't been loaded + var id = obj.id? obj.id: obj; + this._model.data[id] = { + id : id, + parent : '#', + parents : [], + children : [], + children_d : [], + state : { loaded : false }, + li_attr : {}, + a_attr : {}, + parentsload_required : true, + }; + return parent.load_node.call(this, obj, function(obj, status){ + obj.parentsload_required = !status + callback.call(this, obj, status) + }) + } + } + }; +})); diff --git a/civicrm/bower_components/jstree/src/outro.js b/civicrm/bower_components/jstree/src/outro.js new file mode 100644 index 0000000000000000000000000000000000000000..57d3e4820a18414f533bdf477cf27fc7ed142854 --- /dev/null +++ b/civicrm/bower_components/jstree/src/outro.js @@ -0,0 +1 @@ +})); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/sample.js b/civicrm/bower_components/jstree/src/sample.js new file mode 100644 index 0000000000000000000000000000000000000000..2811e75ca0681ed27e394c853b23d72eae23538e --- /dev/null +++ b/civicrm/bower_components/jstree/src/sample.js @@ -0,0 +1,93 @@ +/*global jQuery */ +// wrap in IIFE and pass jQuery as $ +(function ($, undefined) { + "use strict"; + + // some private plugin stuff if needed + var private_var = null; + + // extending the defaults + $.jstree.defaults.sample = { + sample_option : 'sample_val' + }; + + // the actual plugin code + $.jstree.plugins.sample = function (options, parent) { + // own function + this.sample_function = function (arg) { + // you can chain this method if needed and available + if(parent.sample_function) { parent.sample_function.call(this, arg); } + }; + + // *SPECIAL* FUNCTIONS + this.init = function (el, options) { + // do not forget parent + parent.init.call(this, el, options); + }; + // bind events if needed + this.bind = function () { + // call parent function first + parent.bind.call(this); + // do(stuff); + }; + // unbind events if needed (all in jquery namespace are taken care of by the core) + this.unbind = function () { + // do(stuff); + // call parent function last + parent.unbind.call(this); + }; + this.teardown = function () { + // do not forget parent + parent.teardown.call(this); + }; + // state management - get and restore + this.get_state = function () { + // always get state from parent first + var state = parent.get_state.call(this); + // add own stuff to state + state.sample = { 'var' : 'val' }; + return state; + }; + this.set_state = function (state, callback) { + // only process your part if parent returns true + // there will be multiple times with false + if(parent.set_state.call(this, state, callback)) { + // check the key you set above + if(state.sample) { + // do(stuff); // like calling this.sample_function(state.sample.var); + // remove your part of the state, call again and RETURN FALSE, the next cycle will be TRUE + delete state.sample; + this.set_state(state, callback); + return false; + } + // return true if your state is gone (cleared in the previous step) + return true; + } + // parent was false - return false too + return false; + }; + // node transportation + this.get_json = function (obj, options, flat) { + // get the node from the parent + var tmp = parent.get_json.call(this, obj, options, flat), i, j; + if($.isArray(tmp)) { + for(i = 0, j = tmp.length; i < j; i++) { + tmp[i].sample = 'value'; + } + } + else { + tmp.sample = 'value'; + } + // return the original / modified node + return tmp; + }; + }; + + // attach to document ready if needed + $(function () { + // do(stuff); + }); + + // you can include the sample plugin in all instances by default + $.jstree.defaults.plugins.push("sample"); +})(jQuery); \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/themes/base.less b/civicrm/bower_components/jstree/src/themes/base.less new file mode 100644 index 0000000000000000000000000000000000000000..097e9997a87dca9328e1e2ff399d97022096e6e3 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/base.less @@ -0,0 +1,88 @@ +// base jstree +.jstree-node, .jstree-children, .jstree-container-ul { display:block; margin:0; padding:0; list-style-type:none; list-style-image:none; } +.jstree-node { white-space:nowrap; } +.jstree-anchor { display:inline-block; color:black; white-space:nowrap; padding:0 4px 0 1px; margin:0; vertical-align:top; } +.jstree-anchor:focus { outline:0; } +.jstree-anchor, .jstree-anchor:link, .jstree-anchor:visited, .jstree-anchor:hover, .jstree-anchor:active { text-decoration:none; color:inherit; } +.jstree-icon { display:inline-block; text-decoration:none; margin:0; padding:0; vertical-align:top; text-align:center; } +.jstree-icon:empty { display:inline-block; text-decoration:none; margin:0; padding:0; vertical-align:top; text-align:center; } +.jstree-ocl { cursor:pointer; } +.jstree-leaf > .jstree-ocl { cursor:default; } +.jstree .jstree-open > .jstree-children { display:block; } +.jstree .jstree-closed > .jstree-children, +.jstree .jstree-leaf > .jstree-children { display:none; } +.jstree-anchor > .jstree-themeicon { margin-right:2px; } +.jstree-no-icons .jstree-themeicon, +.jstree-anchor > .jstree-themeicon-hidden { display:none; } +.jstree-hidden, .jstree-node.jstree-hidden { display:none; } + +// base jstree rtl +.jstree-rtl { + .jstree-anchor { padding:0 1px 0 4px; } + .jstree-anchor > .jstree-themeicon { margin-left:2px; margin-right:0; } + .jstree-node { margin-left:0; } + .jstree-container-ul > .jstree-node { margin-right:0; } +} + +// base jstree wholerow +.jstree-wholerow-ul { + position:relative; + display:inline-block; + min-width:100%; + .jstree-leaf > .jstree-ocl { cursor:pointer; } + .jstree-anchor, .jstree-icon { position:relative; } + .jstree-wholerow { width:100%; cursor:pointer; position:absolute; left:0; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } +} + +// base contextmenu +.vakata-context { + display:none; + &, ul { margin:0; padding:2px; position:absolute; background:#f5f5f5; border:1px solid #979797; box-shadow:2px 2px 2px #999999; } + ul { list-style:none; left:100%; margin-top:-2.7em; margin-left:-4px; } + .vakata-context-right ul { left:auto; right:100%; margin-left:auto; margin-right:-4px; } + li { + list-style:none; + > a { + display:block; padding:0 2em 0 2em; text-decoration:none; width:auto; color:black; white-space:nowrap; line-height:2.4em; text-shadow:1px 1px 0 white; border-radius:1px; + &:hover { position:relative; background-color:#e8eff7; box-shadow:0 0 2px #0a6aa1; } + &.vakata-context-parent { background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); background-position:right center; background-repeat:no-repeat; } + } + > a:focus { outline:0; } + } + .vakata-context-hover > a { position:relative; background-color:#e8eff7; box-shadow:0 0 2px #0a6aa1; } + .vakata-context-separator { + > a, > a:hover { background:white; border:0; border-top:1px solid #e2e3e3; height:1px; min-height:1px; max-height:1px; padding:0; margin:0 0 0 2.4em; border-left:1px solid #e0e0e0; text-shadow:0 0 0 transparent; box-shadow:0 0 0 transparent; border-radius:0; } + } + .vakata-contextmenu-disabled { + a, a:hover { color:silver; background-color:transparent; border:0; box-shadow:0 0 0; } + } + li > a { + > i { text-decoration:none; display:inline-block; width:2.4em; height:2.4em; background:transparent; margin:0 0 0 -2em; vertical-align:top; text-align:center; line-height:2.4em; } + > i:empty { width:2.4em; line-height:2.4em; } + .vakata-contextmenu-sep { display:inline-block; width:1px; height:2.4em; background:white; margin:0 0.5em 0 0; border-left:1px solid #e2e3e3; } + } + .vakata-contextmenu-shortcut { font-size:0.8em; color:silver; opacity:0.5; display:none; } +} +.vakata-context-rtl { + ul { left:auto; right:100%; margin-left:auto; margin-right:-4px; } + li > a.vakata-context-parent { background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); background-position:left center; background-repeat:no-repeat; } + .vakata-context-separator > a { margin:0 2.4em 0 0; border-left:0; border-right:1px solid #e2e3e3;} + .vakata-context-left ul { right:auto; left:100%; margin-left:-4px; margin-right:auto; } + li > a { + > i { margin:0 -2em 0 0; } + .vakata-contextmenu-sep { margin:0 0 0 0.5em; border-left-color:white; background:#e2e3e3; } + } +} + +// base drag'n'drop +#jstree-marker { position: absolute; top:0; left:0; margin:-5px 0 0 0; padding:0; border-right:0; border-top:5px solid transparent; border-bottom:5px solid transparent; border-left:5px solid; width:0; height:0; font-size:0; line-height:0; } +#jstree-dnd { + line-height:16px; + margin:0; + padding:4px; + .jstree-icon, + .jstree-copy { display:inline-block; text-decoration:none; margin:0 2px 0 0; padding:0; width:16px; height:16px; } + .jstree-ok { background:green; } + .jstree-er { background:red; } + .jstree-copy { margin:0 2px 0 2px; } +} diff --git a/civicrm/bower_components/jstree/src/themes/default-dark/32px.png b/civicrm/bower_components/jstree/src/themes/default-dark/32px.png new file mode 100644 index 0000000000000000000000000000000000000000..60395729ef6cfda914b211d5a45c9d2c083b3175 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default-dark/32px.png differ diff --git a/civicrm/bower_components/jstree/src/themes/default-dark/40px.png b/civicrm/bower_components/jstree/src/themes/default-dark/40px.png new file mode 100644 index 0000000000000000000000000000000000000000..002af360d04324dd30ef3c19116c738da7e06105 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default-dark/40px.png differ diff --git a/civicrm/bower_components/jstree/src/themes/default-dark/style.css b/civicrm/bower_components/jstree/src/themes/default-dark/style.css new file mode 100644 index 0000000000000000000000000000000000000000..3af003f2d558ba972b7612d6f5d0dd24e48339f0 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/default-dark/style.css @@ -0,0 +1,1146 @@ +/* jsTree default dark theme */ +.jstree-node, +.jstree-children, +.jstree-container-ul { + display: block; + margin: 0; + padding: 0; + list-style-type: none; + list-style-image: none; +} +.jstree-node { + white-space: nowrap; +} +.jstree-anchor { + display: inline-block; + color: black; + white-space: nowrap; + padding: 0 4px 0 1px; + margin: 0; + vertical-align: top; +} +.jstree-anchor:focus { + outline: 0; +} +.jstree-anchor, +.jstree-anchor:link, +.jstree-anchor:visited, +.jstree-anchor:hover, +.jstree-anchor:active { + text-decoration: none; + color: inherit; +} +.jstree-icon { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-icon:empty { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-ocl { + cursor: pointer; +} +.jstree-leaf > .jstree-ocl { + cursor: default; +} +.jstree .jstree-open > .jstree-children { + display: block; +} +.jstree .jstree-closed > .jstree-children, +.jstree .jstree-leaf > .jstree-children { + display: none; +} +.jstree-anchor > .jstree-themeicon { + margin-right: 2px; +} +.jstree-no-icons .jstree-themeicon, +.jstree-anchor > .jstree-themeicon-hidden { + display: none; +} +.jstree-hidden, +.jstree-node.jstree-hidden { + display: none; +} +.jstree-rtl .jstree-anchor { + padding: 0 1px 0 4px; +} +.jstree-rtl .jstree-anchor > .jstree-themeicon { + margin-left: 2px; + margin-right: 0; +} +.jstree-rtl .jstree-node { + margin-left: 0; +} +.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; +} +.jstree-wholerow-ul { + position: relative; + display: inline-block; + min-width: 100%; +} +.jstree-wholerow-ul .jstree-leaf > .jstree-ocl { + cursor: pointer; +} +.jstree-wholerow-ul .jstree-anchor, +.jstree-wholerow-ul .jstree-icon { + position: relative; +} +.jstree-wholerow-ul .jstree-wholerow { + width: 100%; + cursor: pointer; + position: absolute; + left: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.vakata-context { + display: none; +} +.vakata-context, +.vakata-context ul { + margin: 0; + padding: 2px; + position: absolute; + background: #f5f5f5; + border: 1px solid #979797; + box-shadow: 2px 2px 2px #999999; +} +.vakata-context ul { + list-style: none; + left: 100%; + margin-top: -2.7em; + margin-left: -4px; +} +.vakata-context .vakata-context-right ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context li { + list-style: none; +} +.vakata-context li > a { + display: block; + padding: 0 2em 0 2em; + text-decoration: none; + width: auto; + color: black; + white-space: nowrap; + line-height: 2.4em; + text-shadow: 1px 1px 0 white; + border-radius: 1px; +} +.vakata-context li > a:hover { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); + background-position: right center; + background-repeat: no-repeat; +} +.vakata-context li > a:focus { + outline: 0; +} +.vakata-context .vakata-context-hover > a { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context .vakata-context-separator > a, +.vakata-context .vakata-context-separator > a:hover { + background: white; + border: 0; + border-top: 1px solid #e2e3e3; + height: 1px; + min-height: 1px; + max-height: 1px; + padding: 0; + margin: 0 0 0 2.4em; + border-left: 1px solid #e0e0e0; + text-shadow: 0 0 0 transparent; + box-shadow: 0 0 0 transparent; + border-radius: 0; +} +.vakata-context .vakata-contextmenu-disabled a, +.vakata-context .vakata-contextmenu-disabled a:hover { + color: silver; + background-color: transparent; + border: 0; + box-shadow: 0 0 0; +} +.vakata-context li > a > i { + text-decoration: none; + display: inline-block; + width: 2.4em; + height: 2.4em; + background: transparent; + margin: 0 0 0 -2em; + vertical-align: top; + text-align: center; + line-height: 2.4em; +} +.vakata-context li > a > i:empty { + width: 2.4em; + line-height: 2.4em; +} +.vakata-context li > a .vakata-contextmenu-sep { + display: inline-block; + width: 1px; + height: 2.4em; + background: white; + margin: 0 0.5em 0 0; + border-left: 1px solid #e2e3e3; +} +.vakata-context .vakata-contextmenu-shortcut { + font-size: 0.8em; + color: silver; + opacity: 0.5; + display: none; +} +.vakata-context-rtl ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context-rtl li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); + background-position: left center; + background-repeat: no-repeat; +} +.vakata-context-rtl .vakata-context-separator > a { + margin: 0 2.4em 0 0; + border-left: 0; + border-right: 1px solid #e2e3e3; +} +.vakata-context-rtl .vakata-context-left ul { + right: auto; + left: 100%; + margin-left: -4px; + margin-right: auto; +} +.vakata-context-rtl li > a > i { + margin: 0 -2em 0 0; +} +.vakata-context-rtl li > a .vakata-contextmenu-sep { + margin: 0 0 0 0.5em; + border-left-color: white; + background: #e2e3e3; +} +#jstree-marker { + position: absolute; + top: 0; + left: 0; + margin: -5px 0 0 0; + padding: 0; + border-right: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid; + width: 0; + height: 0; + font-size: 0; + line-height: 0; +} +#jstree-dnd { + line-height: 16px; + margin: 0; + padding: 4px; +} +#jstree-dnd .jstree-icon, +#jstree-dnd .jstree-copy { + display: inline-block; + text-decoration: none; + margin: 0 2px 0 0; + padding: 0; + width: 16px; + height: 16px; +} +#jstree-dnd .jstree-ok { + background: green; +} +#jstree-dnd .jstree-er { + background: red; +} +#jstree-dnd .jstree-copy { + margin: 0 2px 0 2px; +} +.jstree-default-dark .jstree-node, +.jstree-default-dark .jstree-icon { + background-repeat: no-repeat; + background-color: transparent; +} +.jstree-default-dark .jstree-anchor, +.jstree-default-dark .jstree-animated, +.jstree-default-dark .jstree-wholerow { + transition: background-color 0.15s, box-shadow 0.15s; +} +.jstree-default-dark .jstree-hovered { + background: #555555; + border-radius: 2px; + box-shadow: inset 0 0 1px #555555; +} +.jstree-default-dark .jstree-context { + background: #555555; + border-radius: 2px; + box-shadow: inset 0 0 1px #555555; +} +.jstree-default-dark .jstree-clicked { + background: #5fa2db; + border-radius: 2px; + box-shadow: inset 0 0 1px #666666; +} +.jstree-default-dark .jstree-no-icons .jstree-anchor > .jstree-themeicon { + display: none; +} +.jstree-default-dark .jstree-disabled { + background: transparent; + color: #666666; +} +.jstree-default-dark .jstree-disabled.jstree-hovered { + background: transparent; + box-shadow: none; +} +.jstree-default-dark .jstree-disabled.jstree-clicked { + background: #333333; +} +.jstree-default-dark .jstree-disabled > .jstree-icon { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark .jstree-search { + font-style: italic; + color: #ffffff; + font-weight: bold; +} +.jstree-default-dark .jstree-no-checkboxes .jstree-checkbox { + display: none !important; +} +.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked { + background: transparent; + box-shadow: none; +} +.jstree-default-dark.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered { + background: #555555; +} +.jstree-default-dark.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked { + background: transparent; +} +.jstree-default-dark.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered { + background: #555555; +} +.jstree-default-dark > .jstree-striped { + min-width: 100%; + display: inline-block; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; +} +.jstree-default-dark > .jstree-wholerow-ul .jstree-hovered, +.jstree-default-dark > .jstree-wholerow-ul .jstree-clicked { + background: transparent; + box-shadow: none; + border-radius: 0; +} +.jstree-default-dark .jstree-wholerow { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.jstree-default-dark .jstree-wholerow-hovered { + background: #555555; +} +.jstree-default-dark .jstree-wholerow-clicked { + background: #5fa2db; + background: -webkit-linear-gradient(top, #5fa2db 0%, #5fa2db 100%); + background: linear-gradient(to bottom, #5fa2db 0%, #5fa2db 100%); +} +.jstree-default-dark .jstree-node { + min-height: 24px; + line-height: 24px; + margin-left: 24px; + min-width: 24px; +} +.jstree-default-dark .jstree-anchor { + line-height: 24px; + height: 24px; +} +.jstree-default-dark .jstree-icon { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default-dark .jstree-icon:empty { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default-dark.jstree-rtl .jstree-node { + margin-right: 24px; +} +.jstree-default-dark .jstree-wholerow { + height: 24px; +} +.jstree-default-dark .jstree-node, +.jstree-default-dark .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark .jstree-node { + background-position: -292px -4px; + background-repeat: repeat-y; +} +.jstree-default-dark .jstree-last { + background: transparent; +} +.jstree-default-dark .jstree-open > .jstree-ocl { + background-position: -132px -4px; +} +.jstree-default-dark .jstree-closed > .jstree-ocl { + background-position: -100px -4px; +} +.jstree-default-dark .jstree-leaf > .jstree-ocl { + background-position: -68px -4px; +} +.jstree-default-dark .jstree-themeicon { + background-position: -260px -4px; +} +.jstree-default-dark > .jstree-no-dots .jstree-node, +.jstree-default-dark > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -4px; +} +.jstree-default-dark > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -4px; +} +.jstree-default-dark .jstree-disabled { + background: transparent; +} +.jstree-default-dark .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark .jstree-checkbox { + background-position: -164px -4px; +} +.jstree-default-dark .jstree-checkbox:hover { + background-position: -164px -36px; +} +.jstree-default-dark.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark .jstree-checked > .jstree-checkbox { + background-position: -228px -4px; +} +.jstree-default-dark.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark .jstree-checked > .jstree-checkbox:hover { + background-position: -228px -36px; +} +.jstree-default-dark .jstree-anchor > .jstree-undetermined { + background-position: -196px -4px; +} +.jstree-default-dark .jstree-anchor > .jstree-undetermined:hover { + background-position: -196px -36px; +} +.jstree-default-dark .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark > .jstree-striped { + background-size: auto 48px; +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -132px -36px; +} +.jstree-default-dark.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -100px -36px; +} +.jstree-default-dark.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -68px -36px; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -36px; +} +.jstree-default-dark.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -36px; +} +.jstree-default-dark .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark .jstree-file { + background: url("32px.png") -100px -68px no-repeat; +} +.jstree-default-dark .jstree-folder { + background: url("32px.png") -260px -4px no-repeat; +} +.jstree-default-dark > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark { + line-height: 24px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark .jstree-ok, +#jstree-dnd.jstree-default-dark .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark i { + background: transparent; + width: 24px; + height: 24px; + line-height: 24px; +} +#jstree-dnd.jstree-default-dark .jstree-ok { + background-position: -4px -68px; +} +#jstree-dnd.jstree-default-dark .jstree-er { + background-position: -36px -68px; +} +.jstree-default-dark .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark .jstree-ellipsis .jstree-anchor { + width: calc(100% - 29px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small .jstree-node { + min-height: 18px; + line-height: 18px; + margin-left: 18px; + min-width: 18px; +} +.jstree-default-dark-small .jstree-anchor { + line-height: 18px; + height: 18px; +} +.jstree-default-dark-small .jstree-icon { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-dark-small .jstree-icon:empty { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + margin-right: 18px; +} +.jstree-default-dark-small .jstree-wholerow { + height: 18px; +} +.jstree-default-dark-small .jstree-node, +.jstree-default-dark-small .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark-small .jstree-node { + background-position: -295px -7px; + background-repeat: repeat-y; +} +.jstree-default-dark-small .jstree-last { + background: transparent; +} +.jstree-default-dark-small .jstree-open > .jstree-ocl { + background-position: -135px -7px; +} +.jstree-default-dark-small .jstree-closed > .jstree-ocl { + background-position: -103px -7px; +} +.jstree-default-dark-small .jstree-leaf > .jstree-ocl { + background-position: -71px -7px; +} +.jstree-default-dark-small .jstree-themeicon { + background-position: -263px -7px; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-node, +.jstree-default-dark-small > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -7px; +} +.jstree-default-dark-small > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -7px; +} +.jstree-default-dark-small .jstree-disabled { + background: transparent; +} +.jstree-default-dark-small .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark-small .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark-small .jstree-checkbox { + background-position: -167px -7px; +} +.jstree-default-dark-small .jstree-checkbox:hover { + background-position: -167px -39px; +} +.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark-small .jstree-checked > .jstree-checkbox { + background-position: -231px -7px; +} +.jstree-default-dark-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark-small .jstree-checked > .jstree-checkbox:hover { + background-position: -231px -39px; +} +.jstree-default-dark-small .jstree-anchor > .jstree-undetermined { + background-position: -199px -7px; +} +.jstree-default-dark-small .jstree-anchor > .jstree-undetermined:hover { + background-position: -199px -39px; +} +.jstree-default-dark-small .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark-small > .jstree-striped { + background-size: auto 36px; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -135px -39px; +} +.jstree-default-dark-small.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -103px -39px; +} +.jstree-default-dark-small.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -71px -39px; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -39px; +} +.jstree-default-dark-small.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -39px; +} +.jstree-default-dark-small .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark-small > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark-small .jstree-file { + background: url("32px.png") -103px -71px no-repeat; +} +.jstree-default-dark-small .jstree-folder { + background: url("32px.png") -263px -7px no-repeat; +} +.jstree-default-dark-small > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark-small { + line-height: 18px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark-small .jstree-ok, +#jstree-dnd.jstree-default-dark-small .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark-small i { + background: transparent; + width: 18px; + height: 18px; + line-height: 18px; +} +#jstree-dnd.jstree-default-dark-small .jstree-ok { + background-position: -7px -71px; +} +#jstree-dnd.jstree-default-dark-small .jstree-er { + background-position: -39px -71px; +} +.jstree-default-dark-small .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark-small .jstree-ellipsis .jstree-anchor { + width: calc(100% - 23px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark-small .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large .jstree-node { + min-height: 32px; + line-height: 32px; + margin-left: 32px; + min-width: 32px; +} +.jstree-default-dark-large .jstree-anchor { + line-height: 32px; + height: 32px; +} +.jstree-default-dark-large .jstree-icon { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-dark-large .jstree-icon:empty { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + margin-right: 32px; +} +.jstree-default-dark-large .jstree-wholerow { + height: 32px; +} +.jstree-default-dark-large .jstree-node, +.jstree-default-dark-large .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-dark-large .jstree-node { + background-position: -288px 0px; + background-repeat: repeat-y; +} +.jstree-default-dark-large .jstree-last { + background: transparent; +} +.jstree-default-dark-large .jstree-open > .jstree-ocl { + background-position: -128px 0px; +} +.jstree-default-dark-large .jstree-closed > .jstree-ocl { + background-position: -96px 0px; +} +.jstree-default-dark-large .jstree-leaf > .jstree-ocl { + background-position: -64px 0px; +} +.jstree-default-dark-large .jstree-themeicon { + background-position: -256px 0px; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-node, +.jstree-default-dark-large > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px 0px; +} +.jstree-default-dark-large > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px 0px; +} +.jstree-default-dark-large .jstree-disabled { + background: transparent; +} +.jstree-default-dark-large .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-dark-large .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-dark-large .jstree-checkbox { + background-position: -160px 0px; +} +.jstree-default-dark-large .jstree-checkbox:hover { + background-position: -160px -32px; +} +.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-dark-large .jstree-checked > .jstree-checkbox { + background-position: -224px 0px; +} +.jstree-default-dark-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-dark-large .jstree-checked > .jstree-checkbox:hover { + background-position: -224px -32px; +} +.jstree-default-dark-large .jstree-anchor > .jstree-undetermined { + background-position: -192px 0px; +} +.jstree-default-dark-large .jstree-anchor > .jstree-undetermined:hover { + background-position: -192px -32px; +} +.jstree-default-dark-large .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-dark-large > .jstree-striped { + background-size: auto 64px; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -128px -32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -96px -32px; +} +.jstree-default-dark-large.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -64px -32px; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px -32px; +} +.jstree-default-dark-large.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px -32px; +} +.jstree-default-dark-large .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-dark-large > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-dark-large .jstree-file { + background: url("32px.png") -96px -64px no-repeat; +} +.jstree-default-dark-large .jstree-folder { + background: url("32px.png") -256px 0px no-repeat; +} +.jstree-default-dark-large > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-dark-large { + line-height: 32px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-dark-large .jstree-ok, +#jstree-dnd.jstree-default-dark-large .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-dark-large i { + background: transparent; + width: 32px; + height: 32px; + line-height: 32px; +} +#jstree-dnd.jstree-default-dark-large .jstree-ok { + background-position: 0px -64px; +} +#jstree-dnd.jstree-default-dark-large .jstree-er { + background-position: -32px -64px; +} +.jstree-default-dark-large .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-dark-large .jstree-ellipsis .jstree-anchor { + width: calc(100% - 37px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-dark-large .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} +@media (max-width: 768px) { + #jstree-dnd.jstree-dnd-responsive { + line-height: 40px; + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + #jstree-dnd.jstree-dnd-responsive > i { + background: transparent; + width: 40px; + height: 40px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-ok { + background-image: url("40px.png"); + background-position: 0 -200px; + background-size: 120px 240px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-er { + background-image: url("40px.png"); + background-position: -40px -200px; + background-size: 120px 240px; + } + #jstree-marker.jstree-dnd-responsive { + border-left-width: 10px; + border-top-width: 10px; + border-bottom-width: 10px; + margin-top: -10px; + } +} +@media (max-width: 768px) { + .jstree-default-dark-responsive { + /* + .jstree-open > .jstree-ocl, + .jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; } + */ + } + .jstree-default-dark-responsive .jstree-icon { + background-image: url("40px.png"); + } + .jstree-default-dark-responsive .jstree-node, + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-dark-responsive .jstree-node { + min-height: 40px; + line-height: 40px; + margin-left: 40px; + min-width: 40px; + white-space: nowrap; + } + .jstree-default-dark-responsive .jstree-anchor { + line-height: 40px; + height: 40px; + } + .jstree-default-dark-responsive .jstree-icon, + .jstree-default-dark-responsive .jstree-icon:empty { + width: 40px; + height: 40px; + line-height: 40px; + } + .jstree-default-dark-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-node { + margin-left: 0; + margin-right: 40px; + background: transparent; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; + } + .jstree-default-dark-responsive .jstree-ocl, + .jstree-default-dark-responsive .jstree-themeicon, + .jstree-default-dark-responsive .jstree-checkbox { + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl, + .jstree-default-dark-responsive.jstree-rtl .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-dark-responsive .jstree-open > .jstree-ocl { + background-position: 0 0px !important; + } + .jstree-default-dark-responsive .jstree-closed > .jstree-ocl { + background-position: 0 -40px !important; + } + .jstree-default-dark-responsive.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -40px 0px !important; + } + .jstree-default-dark-responsive .jstree-themeicon { + background-position: -40px -40px; + } + .jstree-default-dark-responsive .jstree-checkbox, + .jstree-default-dark-responsive .jstree-checkbox:hover { + background-position: -40px -80px; + } + .jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, + .jstree-default-dark-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, + .jstree-default-dark-responsive .jstree-checked > .jstree-checkbox, + .jstree-default-dark-responsive .jstree-checked > .jstree-checkbox:hover { + background-position: 0 -80px; + } + .jstree-default-dark-responsive .jstree-anchor > .jstree-undetermined, + .jstree-default-dark-responsive .jstree-anchor > .jstree-undetermined:hover { + background-position: 0 -120px; + } + .jstree-default-dark-responsive .jstree-anchor { + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + .jstree-default-dark-responsive > .jstree-striped { + background: transparent; + } + .jstree-default-dark-responsive .jstree-wholerow { + border-top: 1px solid #666666; + border-bottom: 1px solid #000000; + background: #333333; + height: 40px; + } + .jstree-default-dark-responsive .jstree-wholerow-hovered { + background: #555555; + } + .jstree-default-dark-responsive .jstree-wholerow-clicked { + background: #5fa2db; + } + .jstree-default-dark-responsive .jstree-children .jstree-last > .jstree-wholerow { + box-shadow: inset 0 -6px 3px -5px #111111; + } + .jstree-default-dark-responsive .jstree-children .jstree-open > .jstree-wholerow { + box-shadow: inset 0 6px 3px -5px #111111; + border-top: 0; + } + .jstree-default-dark-responsive .jstree-children .jstree-open + .jstree-open { + box-shadow: none; + } + .jstree-default-dark-responsive .jstree-node, + .jstree-default-dark-responsive .jstree-icon, + .jstree-default-dark-responsive .jstree-node > .jstree-ocl, + .jstree-default-dark-responsive .jstree-themeicon, + .jstree-default-dark-responsive .jstree-checkbox { + background-image: url("40px.png"); + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-node { + background-position: -80px 0; + background-repeat: repeat-y; + } + .jstree-default-dark-responsive .jstree-last { + background: transparent; + } + .jstree-default-dark-responsive .jstree-leaf > .jstree-ocl { + background-position: -40px -120px; + } + .jstree-default-dark-responsive .jstree-last > .jstree-ocl { + background-position: -40px -160px; + } + .jstree-default-dark-responsive .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; + } + .jstree-default-dark-responsive .jstree-file { + background: url("40px.png") 0 -160px no-repeat; + background-size: 120px 240px; + } + .jstree-default-dark-responsive .jstree-folder { + background: url("40px.png") -40px -40px no-repeat; + background-size: 120px 240px; + } + .jstree-default-dark-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; + } +} +.jstree-default-dark { + background: #333; +} +.jstree-default-dark .jstree-anchor { + color: #999; + text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5); +} +.jstree-default-dark .jstree-clicked, +.jstree-default-dark .jstree-checked { + color: white; +} +.jstree-default-dark .jstree-hovered { + color: white; +} +#jstree-marker.jstree-default-dark { + border-left-color: #999; + background: transparent; +} +.jstree-default-dark .jstree-anchor > .jstree-icon { + opacity: 0.75; +} +.jstree-default-dark .jstree-clicked > .jstree-icon, +.jstree-default-dark .jstree-hovered > .jstree-icon, +.jstree-default-dark .jstree-checked > .jstree-icon { + opacity: 1; +} +.jstree-default-dark.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default-dark.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-dark-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-dark-large.jstree-rtl .jstree-last { + background: transparent; +} diff --git a/civicrm/bower_components/jstree/src/themes/default-dark/style.less b/civicrm/bower_components/jstree/src/themes/default-dark/style.less new file mode 100644 index 0000000000000000000000000000000000000000..6cab4e672ee771af9148643bdfd8f7b7f716ea04 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/default-dark/style.less @@ -0,0 +1,50 @@ +/* jsTree default dark theme */ +@theme-name: default-dark; +@hovered-bg-color: #555; +@hovered-shadow-color: #555; +@disabled-color: #666666; +@disabled-bg-color: #333333; +@clicked-bg-color: #5fa2db; +@clicked-shadow-color: #666666; +@clicked-gradient-color-1: #5fa2db; +@clicked-gradient-color-2: #5fa2db; +@search-result-color: #ffffff; +@mobile-wholerow-bg-color: #333333; +@mobile-wholerow-shadow: #111111; +@mobile-wholerow-bordert: #666; +@mobile-wholerow-borderb: #000; +@responsive: true; +@image-path: ""; +@base-height: 40px; + +@import "../mixins.less"; +@import "../base.less"; +@import "../main.less"; + +.jstree-@{theme-name} { + background:#333; + .jstree-anchor { color:#999; text-shadow:1px 1px 0 rgba(0,0,0,0.5); } + .jstree-clicked, .jstree-checked { color:white; } + .jstree-hovered { color:white; } + #jstree-marker& { + border-left-color:#999; + background:transparent; + } + .jstree-anchor > .jstree-icon { opacity:0.75; } + .jstree-clicked > .jstree-icon, + .jstree-hovered > .jstree-icon, + .jstree-checked > .jstree-icon { opacity:1; } +} +// theme variants +.jstree-@{theme-name} { + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} +.jstree-@{theme-name}-small { + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} +.jstree-@{theme-name}-large { + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/themes/default-dark/throbber.gif b/civicrm/bower_components/jstree/src/themes/default-dark/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e310e8be219965cda00a2e1e9f3077838152c73 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default-dark/throbber.gif differ diff --git a/civicrm/bower_components/jstree/src/themes/default/32px.png b/civicrm/bower_components/jstree/src/themes/default/32px.png new file mode 100644 index 0000000000000000000000000000000000000000..ac74418d2843d0233fc67c04a59462caa82bd860 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default/32px.png differ diff --git a/civicrm/bower_components/jstree/src/themes/default/40px.png b/civicrm/bower_components/jstree/src/themes/default/40px.png new file mode 100644 index 0000000000000000000000000000000000000000..29273260075f1654bb86a9e3f42c3f32ab5a2d23 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default/40px.png differ diff --git a/civicrm/bower_components/jstree/src/themes/default/style.css b/civicrm/bower_components/jstree/src/themes/default/style.css new file mode 100644 index 0000000000000000000000000000000000000000..616be241beada11266824974dbfa2811d3f8d8bc --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/default/style.css @@ -0,0 +1,1102 @@ +/* jsTree default theme */ +.jstree-node, +.jstree-children, +.jstree-container-ul { + display: block; + margin: 0; + padding: 0; + list-style-type: none; + list-style-image: none; +} +.jstree-node { + white-space: nowrap; +} +.jstree-anchor { + display: inline-block; + color: black; + white-space: nowrap; + padding: 0 4px 0 1px; + margin: 0; + vertical-align: top; +} +.jstree-anchor:focus { + outline: 0; +} +.jstree-anchor, +.jstree-anchor:link, +.jstree-anchor:visited, +.jstree-anchor:hover, +.jstree-anchor:active { + text-decoration: none; + color: inherit; +} +.jstree-icon { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-icon:empty { + display: inline-block; + text-decoration: none; + margin: 0; + padding: 0; + vertical-align: top; + text-align: center; +} +.jstree-ocl { + cursor: pointer; +} +.jstree-leaf > .jstree-ocl { + cursor: default; +} +.jstree .jstree-open > .jstree-children { + display: block; +} +.jstree .jstree-closed > .jstree-children, +.jstree .jstree-leaf > .jstree-children { + display: none; +} +.jstree-anchor > .jstree-themeicon { + margin-right: 2px; +} +.jstree-no-icons .jstree-themeicon, +.jstree-anchor > .jstree-themeicon-hidden { + display: none; +} +.jstree-hidden, +.jstree-node.jstree-hidden { + display: none; +} +.jstree-rtl .jstree-anchor { + padding: 0 1px 0 4px; +} +.jstree-rtl .jstree-anchor > .jstree-themeicon { + margin-left: 2px; + margin-right: 0; +} +.jstree-rtl .jstree-node { + margin-left: 0; +} +.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; +} +.jstree-wholerow-ul { + position: relative; + display: inline-block; + min-width: 100%; +} +.jstree-wholerow-ul .jstree-leaf > .jstree-ocl { + cursor: pointer; +} +.jstree-wholerow-ul .jstree-anchor, +.jstree-wholerow-ul .jstree-icon { + position: relative; +} +.jstree-wholerow-ul .jstree-wholerow { + width: 100%; + cursor: pointer; + position: absolute; + left: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.vakata-context { + display: none; +} +.vakata-context, +.vakata-context ul { + margin: 0; + padding: 2px; + position: absolute; + background: #f5f5f5; + border: 1px solid #979797; + box-shadow: 2px 2px 2px #999999; +} +.vakata-context ul { + list-style: none; + left: 100%; + margin-top: -2.7em; + margin-left: -4px; +} +.vakata-context .vakata-context-right ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context li { + list-style: none; +} +.vakata-context li > a { + display: block; + padding: 0 2em 0 2em; + text-decoration: none; + width: auto; + color: black; + white-space: nowrap; + line-height: 2.4em; + text-shadow: 1px 1px 0 white; + border-radius: 1px; +} +.vakata-context li > a:hover { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); + background-position: right center; + background-repeat: no-repeat; +} +.vakata-context li > a:focus { + outline: 0; +} +.vakata-context .vakata-context-hover > a { + position: relative; + background-color: #e8eff7; + box-shadow: 0 0 2px #0a6aa1; +} +.vakata-context .vakata-context-separator > a, +.vakata-context .vakata-context-separator > a:hover { + background: white; + border: 0; + border-top: 1px solid #e2e3e3; + height: 1px; + min-height: 1px; + max-height: 1px; + padding: 0; + margin: 0 0 0 2.4em; + border-left: 1px solid #e0e0e0; + text-shadow: 0 0 0 transparent; + box-shadow: 0 0 0 transparent; + border-radius: 0; +} +.vakata-context .vakata-contextmenu-disabled a, +.vakata-context .vakata-contextmenu-disabled a:hover { + color: silver; + background-color: transparent; + border: 0; + box-shadow: 0 0 0; +} +.vakata-context li > a > i { + text-decoration: none; + display: inline-block; + width: 2.4em; + height: 2.4em; + background: transparent; + margin: 0 0 0 -2em; + vertical-align: top; + text-align: center; + line-height: 2.4em; +} +.vakata-context li > a > i:empty { + width: 2.4em; + line-height: 2.4em; +} +.vakata-context li > a .vakata-contextmenu-sep { + display: inline-block; + width: 1px; + height: 2.4em; + background: white; + margin: 0 0.5em 0 0; + border-left: 1px solid #e2e3e3; +} +.vakata-context .vakata-contextmenu-shortcut { + font-size: 0.8em; + color: silver; + opacity: 0.5; + display: none; +} +.vakata-context-rtl ul { + left: auto; + right: 100%; + margin-left: auto; + margin-right: -4px; +} +.vakata-context-rtl li > a.vakata-context-parent { + background-image: url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); + background-position: left center; + background-repeat: no-repeat; +} +.vakata-context-rtl .vakata-context-separator > a { + margin: 0 2.4em 0 0; + border-left: 0; + border-right: 1px solid #e2e3e3; +} +.vakata-context-rtl .vakata-context-left ul { + right: auto; + left: 100%; + margin-left: -4px; + margin-right: auto; +} +.vakata-context-rtl li > a > i { + margin: 0 -2em 0 0; +} +.vakata-context-rtl li > a .vakata-contextmenu-sep { + margin: 0 0 0 0.5em; + border-left-color: white; + background: #e2e3e3; +} +#jstree-marker { + position: absolute; + top: 0; + left: 0; + margin: -5px 0 0 0; + padding: 0; + border-right: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid; + width: 0; + height: 0; + font-size: 0; + line-height: 0; +} +#jstree-dnd { + line-height: 16px; + margin: 0; + padding: 4px; +} +#jstree-dnd .jstree-icon, +#jstree-dnd .jstree-copy { + display: inline-block; + text-decoration: none; + margin: 0 2px 0 0; + padding: 0; + width: 16px; + height: 16px; +} +#jstree-dnd .jstree-ok { + background: green; +} +#jstree-dnd .jstree-er { + background: red; +} +#jstree-dnd .jstree-copy { + margin: 0 2px 0 2px; +} +.jstree-default .jstree-node, +.jstree-default .jstree-icon { + background-repeat: no-repeat; + background-color: transparent; +} +.jstree-default .jstree-anchor, +.jstree-default .jstree-animated, +.jstree-default .jstree-wholerow { + transition: background-color 0.15s, box-shadow 0.15s; +} +.jstree-default .jstree-hovered { + background: #e7f4f9; + border-radius: 2px; + box-shadow: inset 0 0 1px #cccccc; +} +.jstree-default .jstree-context { + background: #e7f4f9; + border-radius: 2px; + box-shadow: inset 0 0 1px #cccccc; +} +.jstree-default .jstree-clicked { + background: #beebff; + border-radius: 2px; + box-shadow: inset 0 0 1px #999999; +} +.jstree-default .jstree-no-icons .jstree-anchor > .jstree-themeicon { + display: none; +} +.jstree-default .jstree-disabled { + background: transparent; + color: #666666; +} +.jstree-default .jstree-disabled.jstree-hovered { + background: transparent; + box-shadow: none; +} +.jstree-default .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default .jstree-disabled > .jstree-icon { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default .jstree-search { + font-style: italic; + color: #8b0000; + font-weight: bold; +} +.jstree-default .jstree-no-checkboxes .jstree-checkbox { + display: none !important; +} +.jstree-default.jstree-checkbox-no-clicked .jstree-clicked { + background: transparent; + box-shadow: none; +} +.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered { + background: #e7f4f9; +} +.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked { + background: transparent; +} +.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered { + background: #e7f4f9; +} +.jstree-default > .jstree-striped { + min-width: 100%; + display: inline-block; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; +} +.jstree-default > .jstree-wholerow-ul .jstree-hovered, +.jstree-default > .jstree-wholerow-ul .jstree-clicked { + background: transparent; + box-shadow: none; + border-radius: 0; +} +.jstree-default .jstree-wholerow { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.jstree-default .jstree-wholerow-hovered { + background: #e7f4f9; +} +.jstree-default .jstree-wholerow-clicked { + background: #beebff; + background: -webkit-linear-gradient(top, #beebff 0%, #a8e4ff 100%); + background: linear-gradient(to bottom, #beebff 0%, #a8e4ff 100%); +} +.jstree-default .jstree-node { + min-height: 24px; + line-height: 24px; + margin-left: 24px; + min-width: 24px; +} +.jstree-default .jstree-anchor { + line-height: 24px; + height: 24px; +} +.jstree-default .jstree-icon { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default .jstree-icon:empty { + width: 24px; + height: 24px; + line-height: 24px; +} +.jstree-default.jstree-rtl .jstree-node { + margin-right: 24px; +} +.jstree-default .jstree-wholerow { + height: 24px; +} +.jstree-default .jstree-node, +.jstree-default .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default .jstree-node { + background-position: -292px -4px; + background-repeat: repeat-y; +} +.jstree-default .jstree-last { + background: transparent; +} +.jstree-default .jstree-open > .jstree-ocl { + background-position: -132px -4px; +} +.jstree-default .jstree-closed > .jstree-ocl { + background-position: -100px -4px; +} +.jstree-default .jstree-leaf > .jstree-ocl { + background-position: -68px -4px; +} +.jstree-default .jstree-themeicon { + background-position: -260px -4px; +} +.jstree-default > .jstree-no-dots .jstree-node, +.jstree-default > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -4px; +} +.jstree-default > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -4px; +} +.jstree-default .jstree-disabled { + background: transparent; +} +.jstree-default .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default .jstree-checkbox { + background-position: -164px -4px; +} +.jstree-default .jstree-checkbox:hover { + background-position: -164px -36px; +} +.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default .jstree-checked > .jstree-checkbox { + background-position: -228px -4px; +} +.jstree-default.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default .jstree-checked > .jstree-checkbox:hover { + background-position: -228px -36px; +} +.jstree-default .jstree-anchor > .jstree-undetermined { + background-position: -196px -4px; +} +.jstree-default .jstree-anchor > .jstree-undetermined:hover { + background-position: -196px -36px; +} +.jstree-default .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default > .jstree-striped { + background-size: auto 48px; +} +.jstree-default.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -132px -36px; +} +.jstree-default.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -100px -36px; +} +.jstree-default.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -68px -36px; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -36px -36px; +} +.jstree-default.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -4px -36px; +} +.jstree-default .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default .jstree-file { + background: url("32px.png") -100px -68px no-repeat; +} +.jstree-default .jstree-folder { + background: url("32px.png") -260px -4px no-repeat; +} +.jstree-default > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default { + line-height: 24px; + padding: 0 4px; +} +#jstree-dnd.jstree-default .jstree-ok, +#jstree-dnd.jstree-default .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default i { + background: transparent; + width: 24px; + height: 24px; + line-height: 24px; +} +#jstree-dnd.jstree-default .jstree-ok { + background-position: -4px -68px; +} +#jstree-dnd.jstree-default .jstree-er { + background-position: -36px -68px; +} +.jstree-default .jstree-ellipsis { + overflow: hidden; +} +.jstree-default .jstree-ellipsis .jstree-anchor { + width: calc(100% - 29px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); +} +.jstree-default.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-small .jstree-node { + min-height: 18px; + line-height: 18px; + margin-left: 18px; + min-width: 18px; +} +.jstree-default-small .jstree-anchor { + line-height: 18px; + height: 18px; +} +.jstree-default-small .jstree-icon { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-small .jstree-icon:empty { + width: 18px; + height: 18px; + line-height: 18px; +} +.jstree-default-small.jstree-rtl .jstree-node { + margin-right: 18px; +} +.jstree-default-small .jstree-wholerow { + height: 18px; +} +.jstree-default-small .jstree-node, +.jstree-default-small .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-small .jstree-node { + background-position: -295px -7px; + background-repeat: repeat-y; +} +.jstree-default-small .jstree-last { + background: transparent; +} +.jstree-default-small .jstree-open > .jstree-ocl { + background-position: -135px -7px; +} +.jstree-default-small .jstree-closed > .jstree-ocl { + background-position: -103px -7px; +} +.jstree-default-small .jstree-leaf > .jstree-ocl { + background-position: -71px -7px; +} +.jstree-default-small .jstree-themeicon { + background-position: -263px -7px; +} +.jstree-default-small > .jstree-no-dots .jstree-node, +.jstree-default-small > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-small > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -7px; +} +.jstree-default-small > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -7px; +} +.jstree-default-small .jstree-disabled { + background: transparent; +} +.jstree-default-small .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-small .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-small .jstree-checkbox { + background-position: -167px -7px; +} +.jstree-default-small .jstree-checkbox:hover { + background-position: -167px -39px; +} +.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-small .jstree-checked > .jstree-checkbox { + background-position: -231px -7px; +} +.jstree-default-small.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-small .jstree-checked > .jstree-checkbox:hover { + background-position: -231px -39px; +} +.jstree-default-small .jstree-anchor > .jstree-undetermined { + background-position: -199px -7px; +} +.jstree-default-small .jstree-anchor > .jstree-undetermined:hover { + background-position: -199px -39px; +} +.jstree-default-small .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-small > .jstree-striped { + background-size: auto 36px; +} +.jstree-default-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-small.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -135px -39px; +} +.jstree-default-small.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -103px -39px; +} +.jstree-default-small.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -71px -39px; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -39px -39px; +} +.jstree-default-small.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: -7px -39px; +} +.jstree-default-small .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-small > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-small .jstree-file { + background: url("32px.png") -103px -71px no-repeat; +} +.jstree-default-small .jstree-folder { + background: url("32px.png") -263px -7px no-repeat; +} +.jstree-default-small > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-small { + line-height: 18px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-small .jstree-ok, +#jstree-dnd.jstree-default-small .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-small i { + background: transparent; + width: 18px; + height: 18px; + line-height: 18px; +} +#jstree-dnd.jstree-default-small .jstree-ok { + background-position: -7px -71px; +} +#jstree-dnd.jstree-default-small .jstree-er { + background-position: -39px -71px; +} +.jstree-default-small .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-small .jstree-ellipsis .jstree-anchor { + width: calc(100% - 23px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-small .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-small.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); +} +.jstree-default-small.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-large .jstree-node { + min-height: 32px; + line-height: 32px; + margin-left: 32px; + min-width: 32px; +} +.jstree-default-large .jstree-anchor { + line-height: 32px; + height: 32px; +} +.jstree-default-large .jstree-icon { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-large .jstree-icon:empty { + width: 32px; + height: 32px; + line-height: 32px; +} +.jstree-default-large.jstree-rtl .jstree-node { + margin-right: 32px; +} +.jstree-default-large .jstree-wholerow { + height: 32px; +} +.jstree-default-large .jstree-node, +.jstree-default-large .jstree-icon { + background-image: url("32px.png"); +} +.jstree-default-large .jstree-node { + background-position: -288px 0px; + background-repeat: repeat-y; +} +.jstree-default-large .jstree-last { + background: transparent; +} +.jstree-default-large .jstree-open > .jstree-ocl { + background-position: -128px 0px; +} +.jstree-default-large .jstree-closed > .jstree-ocl { + background-position: -96px 0px; +} +.jstree-default-large .jstree-leaf > .jstree-ocl { + background-position: -64px 0px; +} +.jstree-default-large .jstree-themeicon { + background-position: -256px 0px; +} +.jstree-default-large > .jstree-no-dots .jstree-node, +.jstree-default-large > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-large > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px 0px; +} +.jstree-default-large > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px 0px; +} +.jstree-default-large .jstree-disabled { + background: transparent; +} +.jstree-default-large .jstree-disabled.jstree-hovered { + background: transparent; +} +.jstree-default-large .jstree-disabled.jstree-clicked { + background: #efefef; +} +.jstree-default-large .jstree-checkbox { + background-position: -160px 0px; +} +.jstree-default-large .jstree-checkbox:hover { + background-position: -160px -32px; +} +.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, +.jstree-default-large .jstree-checked > .jstree-checkbox { + background-position: -224px 0px; +} +.jstree-default-large.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, +.jstree-default-large .jstree-checked > .jstree-checkbox:hover { + background-position: -224px -32px; +} +.jstree-default-large .jstree-anchor > .jstree-undetermined { + background-position: -192px 0px; +} +.jstree-default-large .jstree-anchor > .jstree-undetermined:hover { + background-position: -192px -32px; +} +.jstree-default-large .jstree-checkbox-disabled { + opacity: 0.8; + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); + /* Firefox 10+ */ + filter: gray; + /* IE6-9 */ + -webkit-filter: grayscale(100%); + /* Chrome 19+ & Safari 6+ */ +} +.jstree-default-large > .jstree-striped { + background-size: auto 64px; +} +.jstree-default-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); + background-position: 100% 1px; + background-repeat: repeat-y; +} +.jstree-default-large.jstree-rtl .jstree-last { + background: transparent; +} +.jstree-default-large.jstree-rtl .jstree-open > .jstree-ocl { + background-position: -128px -32px; +} +.jstree-default-large.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -96px -32px; +} +.jstree-default-large.jstree-rtl .jstree-leaf > .jstree-ocl { + background-position: -64px -32px; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-node, +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-leaf > .jstree-ocl { + background: transparent; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-open > .jstree-ocl { + background-position: -32px -32px; +} +.jstree-default-large.jstree-rtl > .jstree-no-dots .jstree-closed > .jstree-ocl { + background-position: 0px -32px; +} +.jstree-default-large .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; +} +.jstree-default-large > .jstree-container-ul .jstree-loading > .jstree-ocl { + background: url("throbber.gif") center center no-repeat; +} +.jstree-default-large .jstree-file { + background: url("32px.png") -96px -64px no-repeat; +} +.jstree-default-large .jstree-folder { + background: url("32px.png") -256px 0px no-repeat; +} +.jstree-default-large > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; +} +#jstree-dnd.jstree-default-large { + line-height: 32px; + padding: 0 4px; +} +#jstree-dnd.jstree-default-large .jstree-ok, +#jstree-dnd.jstree-default-large .jstree-er { + background-image: url("32px.png"); + background-repeat: no-repeat; + background-color: transparent; +} +#jstree-dnd.jstree-default-large i { + background: transparent; + width: 32px; + height: 32px; + line-height: 32px; +} +#jstree-dnd.jstree-default-large .jstree-ok { + background-position: 0px -64px; +} +#jstree-dnd.jstree-default-large .jstree-er { + background-position: -32px -64px; +} +.jstree-default-large .jstree-ellipsis { + overflow: hidden; +} +.jstree-default-large .jstree-ellipsis .jstree-anchor { + width: calc(100% - 37px); + text-overflow: ellipsis; + overflow: hidden; +} +.jstree-default-large .jstree-ellipsis.jstree-no-icons .jstree-anchor { + width: calc(100% - 5px); +} +.jstree-default-large.jstree-rtl .jstree-node { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); +} +.jstree-default-large.jstree-rtl .jstree-last { + background: transparent; +} +@media (max-width: 768px) { + #jstree-dnd.jstree-dnd-responsive { + line-height: 40px; + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + #jstree-dnd.jstree-dnd-responsive > i { + background: transparent; + width: 40px; + height: 40px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-ok { + background-image: url("40px.png"); + background-position: 0 -200px; + background-size: 120px 240px; + } + #jstree-dnd.jstree-dnd-responsive > .jstree-er { + background-image: url("40px.png"); + background-position: -40px -200px; + background-size: 120px 240px; + } + #jstree-marker.jstree-dnd-responsive { + border-left-width: 10px; + border-top-width: 10px; + border-bottom-width: 10px; + margin-top: -10px; + } +} +@media (max-width: 768px) { + .jstree-default-responsive { + /* + .jstree-open > .jstree-ocl, + .jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; } + */ + } + .jstree-default-responsive .jstree-icon { + background-image: url("40px.png"); + } + .jstree-default-responsive .jstree-node, + .jstree-default-responsive .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-responsive .jstree-node { + min-height: 40px; + line-height: 40px; + margin-left: 40px; + min-width: 40px; + white-space: nowrap; + } + .jstree-default-responsive .jstree-anchor { + line-height: 40px; + height: 40px; + } + .jstree-default-responsive .jstree-icon, + .jstree-default-responsive .jstree-icon:empty { + width: 40px; + height: 40px; + line-height: 40px; + } + .jstree-default-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + } + .jstree-default-responsive.jstree-rtl .jstree-node { + margin-left: 0; + margin-right: 40px; + background: transparent; + } + .jstree-default-responsive.jstree-rtl .jstree-container-ul > .jstree-node { + margin-right: 0; + } + .jstree-default-responsive .jstree-ocl, + .jstree-default-responsive .jstree-themeicon, + .jstree-default-responsive .jstree-checkbox { + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-leaf > .jstree-ocl, + .jstree-default-responsive.jstree-rtl .jstree-leaf > .jstree-ocl { + background: transparent; + } + .jstree-default-responsive .jstree-open > .jstree-ocl { + background-position: 0 0px !important; + } + .jstree-default-responsive .jstree-closed > .jstree-ocl { + background-position: 0 -40px !important; + } + .jstree-default-responsive.jstree-rtl .jstree-closed > .jstree-ocl { + background-position: -40px 0px !important; + } + .jstree-default-responsive .jstree-themeicon { + background-position: -40px -40px; + } + .jstree-default-responsive .jstree-checkbox, + .jstree-default-responsive .jstree-checkbox:hover { + background-position: -40px -80px; + } + .jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, + .jstree-default-responsive.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, + .jstree-default-responsive .jstree-checked > .jstree-checkbox, + .jstree-default-responsive .jstree-checked > .jstree-checkbox:hover { + background-position: 0 -80px; + } + .jstree-default-responsive .jstree-anchor > .jstree-undetermined, + .jstree-default-responsive .jstree-anchor > .jstree-undetermined:hover { + background-position: 0 -120px; + } + .jstree-default-responsive .jstree-anchor { + font-weight: bold; + font-size: 1.1em; + text-shadow: 1px 1px white; + } + .jstree-default-responsive > .jstree-striped { + background: transparent; + } + .jstree-default-responsive .jstree-wholerow { + border-top: 1px solid rgba(255, 255, 255, 0.7); + border-bottom: 1px solid rgba(64, 64, 64, 0.2); + background: #ebebeb; + height: 40px; + } + .jstree-default-responsive .jstree-wholerow-hovered { + background: #e7f4f9; + } + .jstree-default-responsive .jstree-wholerow-clicked { + background: #beebff; + } + .jstree-default-responsive .jstree-children .jstree-last > .jstree-wholerow { + box-shadow: inset 0 -6px 3px -5px #666666; + } + .jstree-default-responsive .jstree-children .jstree-open > .jstree-wholerow { + box-shadow: inset 0 6px 3px -5px #666666; + border-top: 0; + } + .jstree-default-responsive .jstree-children .jstree-open + .jstree-open { + box-shadow: none; + } + .jstree-default-responsive .jstree-node, + .jstree-default-responsive .jstree-icon, + .jstree-default-responsive .jstree-node > .jstree-ocl, + .jstree-default-responsive .jstree-themeicon, + .jstree-default-responsive .jstree-checkbox { + background-image: url("40px.png"); + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-node { + background-position: -80px 0; + background-repeat: repeat-y; + } + .jstree-default-responsive .jstree-last { + background: transparent; + } + .jstree-default-responsive .jstree-leaf > .jstree-ocl { + background-position: -40px -120px; + } + .jstree-default-responsive .jstree-last > .jstree-ocl { + background-position: -40px -160px; + } + .jstree-default-responsive .jstree-themeicon-custom { + background-color: transparent; + background-image: none; + background-position: 0 0; + } + .jstree-default-responsive .jstree-file { + background: url("40px.png") 0 -160px no-repeat; + background-size: 120px 240px; + } + .jstree-default-responsive .jstree-folder { + background: url("40px.png") -40px -40px no-repeat; + background-size: 120px 240px; + } + .jstree-default-responsive > .jstree-container-ul > .jstree-node { + margin-left: 0; + margin-right: 0; + } +} diff --git a/civicrm/bower_components/jstree/src/themes/default/style.less b/civicrm/bower_components/jstree/src/themes/default/style.less new file mode 100644 index 0000000000000000000000000000000000000000..88b6cab27933cf14a8a51b5219d9fc84d6a7a439 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/default/style.less @@ -0,0 +1,22 @@ +/* jsTree default theme */ +@theme-name: default; +@hovered-bg-color: #e7f4f9; +@hovered-shadow-color: #cccccc; +@disabled-color: #666666; +@disabled-bg-color: #efefef; +@clicked-bg-color: #beebff; +@clicked-shadow-color: #999999; +@clicked-gradient-color-1: #beebff; +@clicked-gradient-color-2: #a8e4ff; +@search-result-color: #8b0000; +@mobile-wholerow-bg-color: #ebebeb; +@mobile-wholerow-shadow: #666666; +@mobile-wholerow-bordert: rgba(255,255,255,0.7); +@mobile-wholerow-borderb: rgba(64,64,64,0.2); +@responsive: true; +@image-path: ""; +@base-height: 40px; + +@import "../mixins.less"; +@import "../base.less"; +@import "../main.less"; \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/themes/default/throbber.gif b/civicrm/bower_components/jstree/src/themes/default/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 Binary files /dev/null and b/civicrm/bower_components/jstree/src/themes/default/throbber.gif differ diff --git a/civicrm/bower_components/jstree/src/themes/main.less b/civicrm/bower_components/jstree/src/themes/main.less new file mode 100644 index 0000000000000000000000000000000000000000..8616cc039f15f2ce09e6a12a4943291455c6546a --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/main.less @@ -0,0 +1,77 @@ +.jstree-@{theme-name} { + .jstree-node, + .jstree-icon { background-repeat:no-repeat; background-color:transparent; } + .jstree-anchor, + .jstree-animated, + .jstree-wholerow { transition:background-color 0.15s, box-shadow 0.15s; } + .jstree-hovered { background:@hovered-bg-color; border-radius:2px; box-shadow:inset 0 0 1px @hovered-shadow-color; } + .jstree-context { background:@hovered-bg-color; border-radius:2px; box-shadow:inset 0 0 1px @hovered-shadow-color; } + .jstree-clicked { background:@clicked-bg-color; border-radius:2px; box-shadow:inset 0 0 1px @clicked-shadow-color; } + .jstree-no-icons .jstree-anchor > .jstree-themeicon { display:none; } + .jstree-disabled { + background:transparent; color:@disabled-color; + &.jstree-hovered { background:transparent; box-shadow:none; } + &.jstree-clicked { background:@disabled-bg-color; } + > .jstree-icon { opacity:0.8; filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); /* Firefox 10+ */ filter: gray; /* IE6-9 */ -webkit-filter: grayscale(100%); /* Chrome 19+ & Safari 6+ */ } + } + // search + .jstree-search { font-style:italic; color:@search-result-color; font-weight:bold; } + // checkboxes + .jstree-no-checkboxes .jstree-checkbox { display:none !important; } + &.jstree-checkbox-no-clicked { + .jstree-clicked { + background:transparent; + box-shadow:none; + &.jstree-hovered { background:@hovered-bg-color; } + } + > .jstree-wholerow-ul .jstree-wholerow-clicked { + background:transparent; + &.jstree-wholerow-hovered { background:@hovered-bg-color; } + } + } + // stripes + > .jstree-striped { min-width:100%; display:inline-block; background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat; } + // wholerow + > .jstree-wholerow-ul .jstree-hovered, + > .jstree-wholerow-ul .jstree-clicked { background:transparent; box-shadow:none; border-radius:0; } + .jstree-wholerow { -moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box; } + .jstree-wholerow-hovered { background:@hovered-bg-color; } + .jstree-wholerow-clicked { .gradient(@clicked-gradient-color-1, @clicked-gradient-color-2); } +} + +// theme variants +.jstree-@{theme-name} { + .jstree-theme(24px, "@{image-path}32px.png", 32px); + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} +.jstree-@{theme-name}-small { + .jstree-theme(18px, "@{image-path}32px.png", 32px); + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} +.jstree-@{theme-name}-large { + .jstree-theme(32px, "@{image-path}32px.png", 32px); + &.jstree-rtl .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg=="); } + &.jstree-rtl .jstree-last { background:transparent; } +} + +// mobile theme attempt +@media (max-width: 768px) { + #jstree-dnd.jstree-dnd-responsive when (@responsive = true) { + line-height:@base-height; font-weight:bold; font-size:1.1em; text-shadow:1px 1px white; + > i { background:transparent; width:@base-height; height:@base-height; } + > .jstree-ok { background-image:url("@{image-path}@{base-height}.png"); background-position:0 -(@base-height * 5); background-size:(@base-height * 3) (@base-height * 6); } + > .jstree-er { background-image:url("@{image-path}@{base-height}.png"); background-position:-(@base-height * 1) -(@base-height * 5); background-size:(@base-height * 3) (@base-height * 6); } + } + #jstree-marker.jstree-dnd-responsive when (@responsive = true) { + border-left-width:10px; + border-top-width:10px; + border-bottom-width:10px; + margin-top:-10px; + } +} + +.jstree-@{theme-name}-responsive when (@responsive = true) { + @import "responsive.less"; +} diff --git a/civicrm/bower_components/jstree/src/themes/mixins.less b/civicrm/bower_components/jstree/src/themes/mixins.less new file mode 100644 index 0000000000000000000000000000000000000000..3018623b2699bf0938120566a0f47d2c72684bc1 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/mixins.less @@ -0,0 +1,105 @@ +.gradient (@color1; @color2) { + background:@color1; + background: -webkit-linear-gradient(top, @color1 0%,@color2 100%); + background: linear-gradient(to bottom, @color1 0%,@color2 100%); +} + +.jstree-theme (@base-height, @image, @image-height) { + @correction: (@image-height - @base-height) / 2; + + .jstree-node { min-height:@base-height; line-height:@base-height; margin-left:@base-height; min-width:@base-height; } + .jstree-anchor { line-height:@base-height; height:@base-height; } + .jstree-icon { width:@base-height; height:@base-height; line-height:@base-height; } + .jstree-icon:empty { width:@base-height; height:@base-height; line-height:@base-height; } + &.jstree-rtl .jstree-node { margin-right:@base-height; } + .jstree-wholerow { height:@base-height; } + + .jstree-node, + .jstree-icon { background-image:url("@{image}"); } + .jstree-node { background-position:-(@image-height * 9 + @correction) -@correction; background-repeat:repeat-y; } + .jstree-last { background:transparent; } + + .jstree-open > .jstree-ocl { background-position:-(@image-height * 4 + @correction) -@correction; } + .jstree-closed > .jstree-ocl { background-position:-(@image-height * 3 + @correction) -@correction; } + .jstree-leaf > .jstree-ocl { background-position:-(@image-height * 2 + @correction) -@correction; } + + .jstree-themeicon { background-position:-(@image-height * 8 + @correction) -@correction; } + + > .jstree-no-dots { + .jstree-node, + .jstree-leaf > .jstree-ocl { background:transparent; } + .jstree-open > .jstree-ocl { background-position:-(@image-height * 1 + @correction) -@correction; } + .jstree-closed > .jstree-ocl { background-position:-@correction -@correction; } + } + + .jstree-disabled { + background:transparent; + &.jstree-hovered { + background:transparent; + } + &.jstree-clicked { + background:#efefef; + } + } + + .jstree-checkbox { + background-position:-(@image-height * 5 + @correction) -@correction; + &:hover { background-position:-(@image-height * 5 + @correction) -(@image-height * 1 + @correction); } + } + + &.jstree-checkbox-selection .jstree-clicked, .jstree-checked { + > .jstree-checkbox { + background-position:-(@image-height * 7 + @correction) -@correction; + &:hover { background-position:-(@image-height * 7 + @correction) -(@image-height * 1 + @correction); } + } + } + .jstree-anchor { + > .jstree-undetermined { + background-position:-(@image-height * 6 + @correction) -@correction; + &:hover { + background-position:-(@image-height * 6 + @correction) -(@image-height * 1 + @correction); + } + } + } + .jstree-checkbox-disabled { opacity:0.8; filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'jstree-grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#jstree-grayscale"); /* Firefox 10+ */ filter: gray; /* IE6-9 */ -webkit-filter: grayscale(100%); /* Chrome 19+ & Safari 6+ */ } + + > .jstree-striped { background-size:auto (@base-height * 2); } + + &.jstree-rtl { + .jstree-node { background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg=="); background-position: 100% 1px; background-repeat:repeat-y; } + .jstree-last { background:transparent; } + .jstree-open > .jstree-ocl { background-position:-(@image-height * 4 + @correction) -(@image-height * 1 + @correction); } + .jstree-closed > .jstree-ocl { background-position:-(@image-height * 3 + @correction) -(@image-height * 1 + @correction); } + .jstree-leaf > .jstree-ocl { background-position:-(@image-height * 2 + @correction) -(@image-height * 1 + @correction); } + > .jstree-no-dots { + .jstree-node, + .jstree-leaf > .jstree-ocl { background:transparent; } + .jstree-open > .jstree-ocl { background-position:-(@image-height * 1 + @correction) -(@image-height * 1 + @correction); } + .jstree-closed > .jstree-ocl { background-position:-@correction -(@image-height * 1 + @correction); } + } + } + .jstree-themeicon-custom { background-color:transparent; background-image:none; background-position:0 0; } + + > .jstree-container-ul .jstree-loading > .jstree-ocl { background:url("@{image-path}throbber.gif") center center no-repeat; } + + .jstree-file { background:url("@{image}") -(@image-height * 3 + @correction) -(@image-height * 2 + @correction) no-repeat; } + .jstree-folder { background:url("@{image}") -(@image-height * 8 + @correction) -(@correction) no-repeat; } + + > .jstree-container-ul > .jstree-node { margin-left:0; margin-right:0; } + + // drag'n'drop + #jstree-dnd& { + line-height:@base-height; padding:0 4px; + .jstree-ok, + .jstree-er { background-image:url("@{image-path}32px.png"); background-repeat:no-repeat; background-color:transparent; } + i { background:transparent; width:@base-height; height:@base-height; line-height:@base-height; } + .jstree-ok { background-position: -(@correction) -(@image-height * 2 + @correction); } + .jstree-er { background-position: -(@image-height * 1 + @correction) -(@image-height * 2 + @correction); } + } + + // ellipsis + .jstree-ellipsis { overflow: hidden; } + // base height + PADDINGS! + .jstree-ellipsis .jstree-anchor { width: calc(100% ~"-" (@base-height + 5px)); text-overflow: ellipsis; overflow: hidden; } + .jstree-ellipsis.jstree-no-icons .jstree-anchor { width: calc(100% ~"-" 5px); } +} diff --git a/civicrm/bower_components/jstree/src/themes/responsive.less b/civicrm/bower_components/jstree/src/themes/responsive.less new file mode 100644 index 0000000000000000000000000000000000000000..46ffa97e068b40a53dac3cfe6f97689f80f0d671 --- /dev/null +++ b/civicrm/bower_components/jstree/src/themes/responsive.less @@ -0,0 +1,67 @@ +@media (max-width: 768px) { + // background image + .jstree-icon { background-image:url("@{image-path}@{base-height}.png"); } + + .jstree-node, + .jstree-leaf > .jstree-ocl { background:transparent; } + + .jstree-node { min-height:@base-height; line-height:@base-height; margin-left:@base-height; min-width:@base-height; white-space:nowrap; } + .jstree-anchor { line-height:@base-height; height:@base-height; } + .jstree-icon, .jstree-icon:empty { width:@base-height; height:@base-height; line-height:@base-height; } + + > .jstree-container-ul > .jstree-node { margin-left:0; } + &.jstree-rtl .jstree-node { margin-left:0; margin-right:@base-height; background:transparent; } + &.jstree-rtl .jstree-container-ul > .jstree-node { margin-right:0; } + + .jstree-ocl, + .jstree-themeicon, + .jstree-checkbox { background-size:(@base-height * 3) (@base-height * 6); } + .jstree-leaf > .jstree-ocl, + &.jstree-rtl .jstree-leaf > .jstree-ocl { background:transparent; } + .jstree-open > .jstree-ocl { background-position:0 0px !important; } + .jstree-closed > .jstree-ocl { background-position:0 -(@base-height * 1) !important; } + &.jstree-rtl .jstree-closed > .jstree-ocl { background-position:-(@base-height * 1) 0px !important; } + + .jstree-themeicon { background-position:-(@base-height * 1) -(@base-height * 1); } + + .jstree-checkbox, .jstree-checkbox:hover { background-position:-(@base-height * 1) -(@base-height * 2); } + &.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox, + &.jstree-checkbox-selection .jstree-clicked > .jstree-checkbox:hover, + .jstree-checked > .jstree-checkbox, + .jstree-checked > .jstree-checkbox:hover { background-position:0 -(@base-height * 2); } + .jstree-anchor > .jstree-undetermined, .jstree-anchor > .jstree-undetermined:hover { background-position:0 -(@base-height * 3); } + + .jstree-anchor { font-weight:bold; font-size:1.1em; text-shadow:1px 1px white; } + + > .jstree-striped { background:transparent; } + .jstree-wholerow { border-top:1px solid @mobile-wholerow-bordert; border-bottom:1px solid @mobile-wholerow-borderb; background:@mobile-wholerow-bg-color; height:@base-height; } + .jstree-wholerow-hovered { background:@hovered-bg-color; } + .jstree-wholerow-clicked { background:@clicked-bg-color; } + + // thanks to PHOTONUI + .jstree-children .jstree-last > .jstree-wholerow { box-shadow: inset 0 -6px 3px -5px @mobile-wholerow-shadow; } + .jstree-children .jstree-open > .jstree-wholerow { box-shadow: inset 0 6px 3px -5px @mobile-wholerow-shadow; border-top:0; } + .jstree-children .jstree-open + .jstree-open { box-shadow:none; } + + // experiment + .jstree-node, + .jstree-icon, + .jstree-node > .jstree-ocl, + .jstree-themeicon, + .jstree-checkbox { background-image:url("@{image-path}@{base-height}.png"); background-size:(@base-height * 3) (@base-height * 6); } + + .jstree-node { background-position:-(@base-height * 2) 0; background-repeat:repeat-y; } + .jstree-last { background:transparent; } + .jstree-leaf > .jstree-ocl { background-position:-(@base-height * 1) -(@base-height * 3); } + .jstree-last > .jstree-ocl { background-position:-(@base-height * 1) -(@base-height * 4); } + /* + .jstree-open > .jstree-ocl, + .jstree-closed > .jstree-ocl { border-radius:20px; background-color:white; } + */ + + .jstree-themeicon-custom { background-color:transparent; background-image:none; background-position:0 0; } + .jstree-file { background:url("@{image-path}@{base-height}.png") 0 -(@base-height * 4) no-repeat; background-size:(@base-height * 3) (@base-height * 6); } + .jstree-folder { background:url("@{image-path}@{base-height}.png") -(@base-height * 1) -(@base-height * 1) no-repeat; background-size:(@base-height * 3) (@base-height * 6); } + + > .jstree-container-ul > .jstree-node { margin-left:0; margin-right:0; } +} \ No newline at end of file diff --git a/civicrm/bower_components/jstree/src/vakata-jstree.js b/civicrm/bower_components/jstree/src/vakata-jstree.js new file mode 100644 index 0000000000000000000000000000000000000000..98388851773238662493854649532804a893d6ff --- /dev/null +++ b/civicrm/bower_components/jstree/src/vakata-jstree.js @@ -0,0 +1,38 @@ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define('jstree.checkbox', ['jquery','jstree'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery'), require('jstree')); + } + else { + factory(jQuery); + } +}(function ($, undefined) { + "use strict"; + if(document.registerElement && Object && Object.create) { + var proto = Object.create(HTMLElement.prototype); + proto.createdCallback = function () { + var c = { core : {}, plugins : [] }, i; + for(i in $.jstree.plugins) { + if($.jstree.plugins.hasOwnProperty(i) && this.attributes[i]) { + c.plugins.push(i); + if(this.getAttribute(i) && JSON.parse(this.getAttribute(i))) { + c[i] = JSON.parse(this.getAttribute(i)); + } + } + } + for(i in $.jstree.defaults.core) { + if($.jstree.defaults.core.hasOwnProperty(i) && this.attributes[i]) { + c.core[i] = JSON.parse(this.getAttribute(i)) || this.getAttribute(i); + } + } + $(this).jstree(c); + }; + // proto.attributeChangedCallback = function (name, previous, value) { }; + try { + document.registerElement("vakata-jstree", { prototype: proto }); + } catch(ignore) { } + } +})); diff --git a/civicrm/civicrm-version.php b/civicrm/civicrm-version.php index a182d86e8cff75b78501ae7a542fb003332fd8d4..9b670cabc5171d924712c5fa2eb5f5cfc5739257 100644 --- a/civicrm/civicrm-version.php +++ b/civicrm/civicrm-version.php @@ -1,7 +1,7 @@ <?php function civicrmVersion( ) { - return array( 'version' => '4.7.16', + return array( 'version' => '4.7.17', 'cms' => 'Wordpress', - 'revision' => '49b3bee36e' ); + 'revision' => 'e0ebb075af' ); } diff --git a/civicrm/css/contactSummary.css b/civicrm/css/contactSummary.css index a0b14924a98e07512a9d748f1d3d760084176809..6a957989da923a37ab5a8d35b1b6485dfda0aa91 100644 --- a/civicrm/css/contactSummary.css +++ b/civicrm/css/contactSummary.css @@ -345,6 +345,30 @@ div#crm-contact-thumbnail { width: 100%; } +#tagtree { + max-height: 500px; + overflow: auto; +} +#tagtree, +#tagtree li.highlighted ul { + background-color: white; +} +#tagtree li.highlighted, +#tagtree li.highlighted-child.jstree-closed { + background-color: #fefcb0; +} +#tagtree li { + margin-top: 5px; +} +#tagtree ins.jstree-icon { + cursor: pointer; + position: relative; + top: -3px; +} +#tagtree input { + margin: 0; +} + #tagGroup table .label { color: #FFF; } diff --git a/civicrm/js/Common.js b/civicrm/js/Common.js index 86f21fb46e73ee6b77ea9e10c84b0f7a965ae16c..4600589652cff76d237258f34d2d781c1c9fe184 100644 --- a/civicrm/js/Common.js +++ b/civicrm/js/Common.js @@ -1522,10 +1522,13 @@ if (!CRM.vars) CRM.vars = {}; $(this).siblings('input:text').val('').trigger('change', ['crmClear']); return false; }) - .on('change', 'input.crm-form-radio:checked, input[allowclear=1]', function(e, context) { + .on('change keyup', 'input.crm-form-radio:checked, input[allowclear=1]', function(e, context) { if (context !== 'crmClear' && ($(this).is(':checked') || ($(this).is('[allowclear=1]') && $(this).val()))) { $(this).siblings('.crm-clear-link').css({visibility: ''}); } + if (context !== 'crmClear' && $(this).is('[allowclear=1]') && $(this).val() === '') { + $(this).siblings('.crm-clear-link').css({visibility: 'hidden'}); + } }) // Allow normal clicking of links within accordions @@ -1658,8 +1661,11 @@ if (!CRM.vars) CRM.vars = {}; return input; case 'string': - // convert iso format - return $.datepicker.parseDate('yy-mm-dd', input.substr(0, 10)); + // convert iso format with or without dashes + if (input.indexOf('-') > 0) { + return $.datepicker.parseDate('yy-mm-dd', input.substr(0, 10)); + } + return $.datepicker.parseDate('yymmdd', input.substr(0, 8)); case 'number': // convert unix timestamp diff --git a/civicrm/js/crm.ajax.js b/civicrm/js/crm.ajax.js index b01e814bf076d3c0613793ef8a43d97d5fd3e69b..262227ea895c2541ad775bde62b26a4f4217b353 100644 --- a/civicrm/js/crm.ajax.js +++ b/civicrm/js/crm.ajax.js @@ -496,7 +496,7 @@ url = $el.attr('href'), popup = $el.data('popup-type') === 'page' ? CRM.loadPage : CRM.loadForm, settings = $el.data('popup-settings') || {}, - formSuccess = false; + formData = false; settings.dialog = settings.dialog || {}; if (e.isDefaultPrevented() || !CRM.config.ajaxPopupsEnabled || !url || $el.is(exclude)) { return; @@ -513,12 +513,12 @@ // Trigger events from the dialog on the original link element $el.trigger('crmPopupOpen', [dialog]); // Listen for success events and buffer them so we only trigger once - dialog.on('crmFormSuccess.crmPopup crmPopupFormSuccess.crmPopup', function() { - formSuccess = true; + dialog.on('crmFormSuccess.crmPopup crmPopupFormSuccess.crmPopup', function(e, data) { + formData = data; }); dialog.on('dialogclose.crmPopup', function(e, data) { - if (formSuccess) { - $el.trigger('crmPopupFormSuccess', [dialog, data]); + if (formData) { + $el.trigger('crmPopupFormSuccess', [dialog, formData]); } $el.trigger('crmPopupClose', [dialog, data]); }); diff --git a/civicrm/js/crm.drupal.js b/civicrm/js/crm.drupal.js index 2f14c499216e2e38bba0c202fc3a4d9b8cc9201d..7ed33666e29a834c01870d5f18cf10c59f83b13b 100644 --- a/civicrm/js/crm.drupal.js +++ b/civicrm/js/crm.drupal.js @@ -10,5 +10,13 @@ CRM.$(function($) { // D7 hack, restore toolbar position (CRM-15341) $('#toolbar').css('z-index', ''); } - }); + }) + // d8 Hack to hide title when it should be (CRM-19960) + .ready(function() { + var pageTitle = $('.page-title'); + var title = $('.page-title').text(); + if ('<span id="crm-remove-title" style="display:none">CiviCRM</span>' == title) { + pageTitle.hide(); + } + }); }); diff --git a/civicrm/packages/DB/DataObject.php b/civicrm/packages/DB/DataObject.php index ca3f70bbee6918e8c2ae788ba5e086f24a03ccb5..9636b9a5fc29d211bd776133d6b8bf844cca1a12 100644 --- a/civicrm/packages/DB/DataObject.php +++ b/civicrm/packages/DB/DataObject.php @@ -3645,7 +3645,7 @@ class DB_DataObject extends DB_DataObject_Overload * @return array of key => value for row */ - function toArray($format = '%s', $hideEmpty = false) + function toArray($format = null, $hideEmpty = false) { global $_DB_DATAOBJECT; $ret = array(); @@ -3659,24 +3659,35 @@ class DB_DataObject extends DB_DataObject_Overload if (!isset($this->$k)) { if (!$hideEmpty) { - $ret[sprintf($format,$k)] = ''; + if ($format === null) + $ret[$k] = ''; + else + $ret[sprintf($format,$k)] = ''; } continue; } // call the overloaded getXXXX() method. - except getLink and getLinks if (method_exists($this,'get'.$k) && !in_array(strtolower($k),array('links','link'))) { - $ret[sprintf($format,$k)] = $this->{'get'.$k}(); + if ($format === null) + $ret[$k] = $this->{'get'.$k}(); + else + $ret[sprintf($format,$k)] = $this->{'get'.$k}(); continue; } // should this call toValue() ??? - $ret[sprintf($format,$k)] = $this->$k; + if ($format === null) + $ret[$k] = $this->$k; + else + $ret[sprintf($format,$k)] = $this->$k; } if (!$this->_link_loaded) { return $ret; } foreach($this->_link_loaded as $k) { - $ret[sprintf($format,$k)] = $this->$k->toArray(); - + if ($format === null) + $ret[$k] = $this->$k->toArray(); + else + $ret[sprintf($format,$k)] = $this->$k->toArray(); } return $ret; diff --git a/civicrm/release-notes.md b/civicrm/release-notes.md index c21ab0bee1d74e9db6a9b9bf58a7d446da633202..9c4d6a3c357374de1ddcef446615901be589e062 100644 --- a/civicrm/release-notes.md +++ b/civicrm/release-notes.md @@ -14,6 +14,15 @@ Other resources for identifying changes are: * https://github.com/civicrm/civicrm-joomla * https://github.com/civicrm/civicrm-wordpress +## CiviCRM 4.7.17 + +Released March 8, 2017 + +- **[Features](release-notes/4.7.17.md#features)** +- **[Bugs resolved](release-notes/4.7.17.md#bugs)** +- **[Miscellany](release-notes/4.7.17.md#misc)** +- **[Credits](release-notes/4.7.17.md#credits)** + ## CiviCRM 4.7.16 Released February 8, 2017 diff --git a/civicrm/release-notes/4.7.17.md b/civicrm/release-notes/4.7.17.md new file mode 100644 index 0000000000000000000000000000000000000000..0d95f91bae9d5ec05f3050a90f5908f15becca52 --- /dev/null +++ b/civicrm/release-notes/4.7.17.md @@ -0,0 +1,556 @@ +# CiviCRM 4.7.17 + +Released March 8, 2017 + +- **[Features](#features)** +- **[Bugs resolved](#bugs)** +- **[Miscellany](#misc)** +- **[Credits](#credits)** + +## <a name="features"></a>Features + +### Core CiviCRM + +- **[CRM-19815](https://issues.civicrm.org/jira/browse/CRM-19815) Make + pseudoconstant code generic in advanced search + ([9908](https://github.com/civicrm/civicrm-core/pull/9908), + [9885](https://github.com/civicrm/civicrm-core/pull/9885), and + [9799](https://github.com/civicrm/civicrm-core/pull/9799))** + + This modifies handling of pseudoconstants (site-wide lists of options) from + specific hard-coded situations to metadata-based fields. This results in + removing slow joins and improves speed. + +- **[CRM-19492](https://issues.civicrm.org/jira/browse/CRM-19492) When merging: + require row to be taken across before changing row settings + ([9902](https://github.com/civicrm/civicrm-core/pull/9902))** + + The interface for merging contacts is clarified so that merge options such as + location type on a field are not available unless the field is marked to be + merged from the contact which is to be deleted. + +- **[CRM-20175](https://issues.civicrm.org/jira/browse/CRM-20175) Increase pager + support to 9999 pages + ([9894](https://github.com/civicrm/civicrm-core/pull/9894))** + + The page number box on search results now allows four-digit page numbers. + +- **[CRM-19934](https://issues.civicrm.org/jira/browse/CRM-19934) Performance + improvement on civicrm_acl_contact_cache + ([9807](https://github.com/civicrm/civicrm-core/pull/9807)) (Partial work)** + + The query for building an ACL cache is simplified to avoid a taxing `OR` + clause. + +- **[CRM-19816](https://issues.civicrm.org/jira/browse/CRM-19816) Improve + activity search filters + ([9841](https://github.com/civicrm/civicrm-core/pull/9841))** + + Using the API to search for activities involving a specific contact is + simplified and standardized across the assignee, source, and target, plus the + generic `contact_id` parameter. + +- **[CRM-19883](https://issues.civicrm.org/jira/browse/CRM-19883) Activity + Priority Field is Not Included in Advanced Search or Activity Reports + ([9816](https://github.com/civicrm/civicrm-core/pull/9816) and + [9800](https://github.com/civicrm/civicrm-core/pull/9800))** + + The Priority field is now available in the Activity Detail and Activity + Summary reports. + +- **[CRM-19938](https://issues.civicrm.org/jira/browse/CRM-19938) Make Civi to + CMS email sync optional + ([9765](https://github.com/civicrm/civicrm-core/pull/9765))** + + There is now an option to disable synchronization of a contact's email address + with their CMS user account. + +- **[CRM-19930](https://issues.civicrm.org/jira/browse/CRM-19930) Patch + DB_DataObject::toArray() to sprintf only as needed + ([9735](https://github.com/civicrm/civicrm-core/pull/9735) and + [177](https://github.com/civicrm/civicrm-packages/pull/177))** + + Database query performance is improved by only running strings through + `sprintf()` when actually necessary. + +- **Extension.download API - Allow downloading without installing + ([9898](https://github.com/civicrm/civicrm-core/pull/9898))** + + The Extension.download API still defaults to downloading and installing an + extension, but a new parameter `install` can be set to `FALSE` in order to + download without installing. + +- **[CRM-20034](https://issues.civicrm.org/jira/browse/CRM-20034) Support "OR" + params in api get + ([9844](https://github.com/civicrm/civicrm-core/pull/9844))** + + Many entities can now be queried with sets of `OR` parameters, returning rows + that meet one of several criteria. The API Explorer displays the `AND`/`OR` + option when it is available. + + Separately, the Activity.get API now allows for searching by the ID of + attached files and allows for joining on EntityTag. + +- **[CRM-19943](https://issues.civicrm.org/jira/browse/CRM-19943) Improve tag + management UI ([9918](https://github.com/civicrm/civicrm-core/pull/9918) and + [9787](https://github.com/civicrm/civicrm-core/pull/9787))** + + A new drag-and-drop interface allows for editing, nesting, and coloring tags. + +- **[CRM-20061](https://issues.civicrm.org/jira/browse/CRM-20061) Allow 'tables' + as a parameter on the revert api + ([9862](https://github.com/civicrm/civicrm-core/pull/9862))** + + This adds the opportunity to specify which tables to revert for a logged + change. + +### CiviContribute + +- **[CRM-20158](https://issues.civicrm.org/jira/browse/CRM-20158) Store card + type and last 4 digits of credit card + ([9876](https://github.com/civicrm/civicrm-core/pull/9876)) (Preliminary + work)** + + The `civicrm_financial_trxn` table now contains fields to store credit card + type (e.g. Visa, MasterCard, etc.) and the last four digits of the card + number, if available. The fields are not yet used by any functions. + +- **[CRM-20022](https://issues.civicrm.org/jira/browse/CRM-20022) Add Batch + Title to Columns, Grouping tabs on Contribution Summary report + ([9838](https://github.com/civicrm/civicrm-core/pull/9838))** + + The Contribution Summary report now has an option to display the title of the + corresponding financial transaction batch. + +### CiviEvent + +- **[CRM-19999](https://issues.civicrm.org/jira/browse/CRM-19999) Soften error + message when registration is closed for an event + ([9823](https://github.com/civicrm/civicrm-core/pull/9823))** + + CiviCRM now says "Sorry" when you attempt to register for an event where + registration is closed. + +### CiviMail + +- **[CRM-20196](https://issues.civicrm.org/jira/browse/CRM-20196) Add a useful + message when the user didn't setup bounce processing properly + ([9906](https://github.com/civicrm/civicrm-core/pull/9906))** + + If you fail to set a domain in the Mail Accounts and send a message through + CiviMail, a log message will note the situation. + +### Backdrop Integration + +- **Add a default layout for CiviCRM admin and ability to configure/set to + default. + ([15](https://github.com/civicrm/civicrm-backdrop/issues/15) and + [20](https://github.com/civicrm/civicrm-backdrop/pull/20))** + + CiviCRM for Backdrop now has a default layout for administration pages. + +## <a name="bugs"></a>Bugs resolved + +### Core CiviCRM + +- **[CRM-19929](https://issues.civicrm.org/jira/browse/CRM-19929) Implement pre + hook for entityTag + ([9733](https://github.com/civicrm/civicrm-core/pull/9733))** + + Updates to `civicrm_entity_tag`--tagging or untagging a contact or + activity--now invoke `hook_civicrm_pre()`. + +- **[CRM-20201](https://issues.civicrm.org/jira/browse/CRM-20201) Manage Tags + page does not work if a tag set does not have created by set + ([9919](https://github.com/civicrm/civicrm-core/pull/9919) and + [9913](https://github.com/civicrm/civicrm-core/pull/9913))** + +- **(Regression) CRM_Mailing_ActionTokens - Degrade gracefully + ([9874](https://github.com/civicrm/civicrm-core/pull/9874))** + + This fixes an issue where scheduled reminders and other non-CiviMail messages + would fail if they inadvertently use CiviMail action tokens. + +- **[CRM-19453](https://issues.civicrm.org/jira/browse/CRM-19453) In Windows + System->Directories fails to display under Joomla + ([9890](https://github.com/civicrm/civicrm-core/pull/9890))** + + This allows Joomla users on Windows to view the Directories settings page + without errors. + +- **[CRM-20144](https://issues.civicrm.org/jira/browse/CRM-20144) API + contact.get group='x' yields ""DB Error: no such field"" + ([9884](https://github.com/civicrm/civicrm-core/pull/9884) and + [9867](https://github.com/civicrm/civicrm-core/pull/9867))** + + This reinstates the feature allowing for contacts to be searched by group + (including smart group) using the API. + +- **Display error message for activity processing + ([9882](https://github.com/civicrm/civicrm-core/pull/9882))** + + The activity processor scheduled job now records the actual error message that + occurred rather than a generic failure message. + +- **ApiExplorer - Fix js error + ([9883](https://github.com/civicrm/civicrm-core/pull/9883))** + +- **[CRM-19693](https://issues.civicrm.org/jira/browse/CRM-19693) Don't show + options for disabled components + ([9459](https://github.com/civicrm/civicrm-core/pull/9459))** + +- **[CRM-19657](https://issues.civicrm.org/jira/browse/CRM-19657) recurring + contribution receipt comes from logged in user + ([9856](https://github.com/civicrm/civicrm-core/pull/9856) and + [9842](https://github.com/civicrm/civicrm-core/pull/9842))** + + This fixes a bug where receipts triggered by an administrator's actions or a + scheduled job now come from system-wide information or the default email + rather than the contact associated with the user who is triggering them. + +- **[CRM-19972](https://issues.civicrm.org/jira/browse/CRM-19972) Add in Post + upgrade message for addition of manage tags permission + ([9808](https://github.com/civicrm/civicrm-core/pull/9808))** + + The "manage tags" permission was added in 4.7.13, but site administrators were + not alerted about it when upgrading. + +- **[CRM-19184](https://issues.civicrm.org/jira/browse/CRM-19184) Activities + target contact list does not truncate + ([9846](https://github.com/civicrm/civicrm-core/pull/9846))** + + When viewing activities, the list of contacts the activity is with should be + limited to the first several. This fixes a regression that listed all the + contacts. + +- **[CRM-18811](https://issues.civicrm.org/jira/browse/CRM-18811) MySQL table + and column aliases can contain spaces + ([8548](https://github.com/civicrm/civicrm-core/pull/8548))** + + This fixes a problem displaying profiles that have location details for a + location type that contains a space. + +- **[CRM-20015](https://issues.civicrm.org/jira/browse/CRM-20015) token values + with ampersand cause error when generating docx letter + ([9834](https://github.com/civicrm/civicrm-core/pull/9834))** + +- **[CRM-19950](https://issues.civicrm.org/jira/browse/CRM-19950) Wrong param + passed to checkPermission function + ([9832](https://github.com/civicrm/civicrm-core/pull/9832) and + [9810](https://github.com/civicrm/civicrm-core/pull/9810))** + +- **[CRM-18464](https://issues.civicrm.org/jira/browse/CRM-18464) Database Error + upgrading to Civicrm 4.7 + ([9679](https://github.com/civicrm/civicrm-core/pull/9679))** + + Some legacy sites had a foreign key from `civicrm_action_schedule` to + `mapping_id` set as an index rather than a proper foreign key. Dropping that + key as part of the upgrade to 4.7.alpha1 resulted in a failed upgrade. The + key is now dropped more safely. + +- **[CRM-19979](https://issues.civicrm.org/jira/browse/CRM-19979) + GroupContact.delete does not work for contacts with status of Pending + ([9797](https://github.com/civicrm/civicrm-core/pull/9797))** + +- **[CRM-19957](https://issues.civicrm.org/jira/browse/CRM-19957) DB Syntax + Error on all Search Form submission + ([9767](https://github.com/civicrm/civicrm-core/pull/9767))** + +- **[CRM-19955](https://issues.civicrm.org/jira/browse/CRM-19955) custom field + image display in contact record retrieve incorrectly + ([9758](https://github.com/civicrm/civicrm-core/pull/9758))** + + This fixes a problem where files uploaded to custom fields were retrieved + according to the ID of the entity they're attached to, not the ID of the files + themselves. + +- **[CRM-19926](https://issues.civicrm.org/jira/browse/CRM-19926) Constituent + Summary Report Filtered by Groups ignores children groups + ([9732](https://github.com/civicrm/civicrm-core/pull/9732))** + +- **[CRM-18427](https://issues.civicrm.org/jira/browse/CRM-18427) Submitted + custom data values not reloaded on form when validation fails + ([9752](https://github.com/civicrm/civicrm-core/pull/9752))** + +- **[CRM-19927](https://issues.civicrm.org/jira/browse/CRM-19927) Error message + when "Add to Group" is pressed with no group selected + ([9731](https://github.com/civicrm/civicrm-core/pull/9731))** + +- **[CRM-19864](https://issues.civicrm.org/jira/browse/CRM-19864) Incorrect URL + in CiviCRM Resources dashlet on Joomla + ([9668](https://github.com/civicrm/civicrm-core/pull/9668))** + + The Configuration Checklist link in the Resources menu was a frontend link in + WordPress and Joomla. + +- **[CRM-20180](https://issues.civicrm.org/jira/browse/CRM-20180) Several + documentation links are malformed + ([9897](https://github.com/civicrm/civicrm-core/pull/9897))** + +- **Handle date formats through metadata (see + [CRM-19490](https://issues.civicrm.org/jira/browse/CRM-19490), + [CRM-18387](https://issues.civicrm.org/jira/browse/CRM-18387), + [CRM-20012](https://issues.civicrm.org/jira/browse/CRM-20012), + [CRM-20011](https://issues.civicrm.org/jira/browse/CRM-20011), + [CRM-15948](https://issues.civicrm.org/jira/browse/CRM-15948), and + [CRM-19911](https://issues.civicrm.org/jira/browse/CRM-19911)) + (([9888](https://github.com/civicrm/civicrm-core/pull/9888), + [9845](https://github.com/civicrm/civicrm-core/pull/9845), + [9843](https://github.com/civicrm/civicrm-core/pull/9843), and + [9830](https://github.com/civicrm/civicrm-core/pull/9830))) (Preliminary work)** + + A variety of problems periodically emerge with date fields, mainly due to the + practically-unique ways of defining and handling each date field. The goal of + this work is to define all date fields through metadata. Changes so far + define the metadata for date fields, but the fields are still generated the + old way. + +- **[CRM-19887](https://issues.civicrm.org/jira/browse/CRM-19887) Activity + Summary report gives DB error on sort by email + ([9690](https://github.com/civicrm/civicrm-core/pull/9690))** + +- **[CRM-19982](https://issues.civicrm.org/jira/browse/CRM-19982) Can't enter + dates in 4.7.16. Can only enter characters in word "birth" + ([9831](https://github.com/civicrm/civicrm-core/pull/9831))** + +- **[CRM-19947](https://issues.civicrm.org/jira/browse/CRM-19947) custom multi + profile: file upload display issue + ([9754](https://github.com/civicrm/civicrm-core/pull/9754))** + + On profiles including fields from multi-record custom data sets, files + uploaded in one record were appearing in other records on the same contact. + +### CiviCase + +- **[CRM-19956](https://issues.civicrm.org/jira/browse/CRM-19956) Moving/Copying + activities between Cases + ([9766](https://github.com/civicrm/civicrm-core/pull/9766))** + + This fixes an issue preventing the selection of a destination case when moving + or copying activities. + +### CiviContribute + +- **[CRM-19830](https://issues.civicrm.org/jira/browse/CRM-19830) Cleanup + contribution search by making non-exportable fields exportable + ([9718](https://github.com/civicrm/civicrm-core/pull/9718))** + +- **[CRM-19793](https://issues.civicrm.org/jira/browse/CRM-19793) Redirect + payment processors that fail result in ugly fatal - be prettier + ([9762](https://github.com/civicrm/civicrm-core/pull/9762))** + +- **[CRM-19949](https://issues.civicrm.org/jira/browse/CRM-19949) Notice appear + when setup profiles contain common field with contribution page + ([9753](https://github.com/civicrm/civicrm-core/pull/9753))** + +- **[CRM-19881](https://issues.civicrm.org/jira/browse/CRM-19881): Time + clobbered in receive_date and trxn_date for api contribution repeattransaction + and completetransaction + ([9680](https://github.com/civicrm/civicrm-core/pull/9680))** + + The API spec for the contribution `gettransaction` and `repeattransaction` + actions did not contain time, so the receive date and transaction dates were + set to midnight. + +- **[CRM-20145](https://issues.civicrm.org/jira/browse/CRM-20145) line_item with + $0 amount may error when creating civicrm_entity_financial_trxn + ([9866](https://github.com/civicrm/civicrm-core/pull/9866))** + +- **[CRM-20048](https://issues.civicrm.org/jira/browse/CRM-20048) PayPal IPNs + not processed if "receiver_email" != "business" + ([9858](https://github.com/civicrm/civicrm-core/pull/9858))** + + This resolves problems if a site's PayPal account has a `receiver_email` that + is different from the main email address for their business account. CiviCRM + now looks for the `business` email. + +- **[CRM-19908](https://issues.civicrm.org/jira/browse/CRM-19908) Fundamental + Fixes for Tax Math Calculations. + ([9711](https://github.com/civicrm/civicrm-core/pull/9711))** + + This change defers rounding of tax amounts until after being multiplied by an + item's quantity and avoids deriving a tax rate from the amount of tax on a + line item. + +- **[CRM-19517](https://issues.civicrm.org/jira/browse/CRM-19517) Show price + field Options that use disabled Financial Types so they can be edited. + ([9763](https://github.com/civicrm/civicrm-core/pull/9763))** + +- **[CRM-19802](https://issues.civicrm.org/jira/browse/CRM-19802) Contribution + page : missing translation + ([9587](https://github.com/civicrm/civicrm-core/pull/9587))** + + This fixes the wrapping of translatable strings in Javascript within page + templates. + +- **[CRM-19873](https://issues.civicrm.org/jira/browse/CRM-19873) + contribute.repeattransaction fails when contribution_recur_id is a test + recurring contribtuion + ([9674](https://github.com/civicrm/civicrm-core/pull/9674))** + +### CiviEvent + +- **[CRM-20004](https://issues.civicrm.org/jira/browse/CRM-20004) Event payment + receipt sent twice + ([9933](https://github.com/civicrm/civicrm-core/pull/9933))** + +- **[CRM-19964](https://issues.civicrm.org/jira/browse/CRM-19964) Event + registration creates contribution without line item + ([9774](https://github.com/civicrm/civicrm-core/pull/9774))** + + This situation occurred if a price set was enabled, no price field was + required, and a user registered for the event without any of the price fields + having a value. + +- **[CRM-19918](https://issues.civicrm.org/jira/browse/CRM-19918) Price field + "Active on" date ignored in Edit Event Registration > "Change Selections" + ([9764](https://github.com/civicrm/civicrm-core/pull/9764))** + +- **[CRM-20170](https://issues.civicrm.org/jira/browse/CRM-20170) Fix attendee + count on event summary report for free events + ([9887](https://github.com/civicrm/civicrm-core/pull/9887))** + +- **[CRM-20013](https://issues.civicrm.org/jira/browse/CRM-20013) Localization + for participant status on Event Income Report (Summary) + ([9833](https://github.com/civicrm/civicrm-core/pull/9833))** + + The participant status was showing the field name rather than the translated + label. + +### CiviMail + +- **[CRM-20016](https://issues.civicrm.org/jira/browse/CRM-20016) Fatal error + processing bounces when email_id IS NULL + ([9837](https://github.com/civicrm/civicrm-core/pull/9837))** + +- **[CRM-19924](https://issues.civicrm.org/jira/browse/CRM-19924) Unsubscribe + from a mailing sent to a parent group silently fails + ([9730](https://github.com/civicrm/civicrm-core/pull/9730))** + +### CiviMember + +- **[CRM-19871](https://issues.civicrm.org/jira/browse/CRM-19871) Default + Membership Type not selected - Contribution Form + ([9704](https://github.com/civicrm/civicrm-core/pull/9704))** + + The membership type on contribution pages was defaulting according to weight + rather than the type marked as default. + +- **[CRM-19936](https://issues.civicrm.org/jira/browse/CRM-19936) Membership + line items are duplicated when a membership is created or renewed with + priceset containing multiple memberships + ([9744](https://github.com/civicrm/civicrm-core/pull/9744)) (Partially + fixed)** + + Bug was as described. The cause has been repaired, but the issue is still + pending an action to repair the duplicate line items. + +- **[CRM-20010](https://issues.civicrm.org/jira/browse/CRM-20010) Membership + period_type is required in frontend but not in API. + ([9829](https://github.com/civicrm/civicrm-core/pull/9829))** + +- **[CRM-19945](https://issues.civicrm.org/jira/browse/CRM-19945) + api.contribute.repeattransaction fails to renew membership under certain + conditions ([9792](https://github.com/civicrm/civicrm-core/pull/9792))** + +### Drupal Integration Modules + +- **[CRM-19910](https://issues.civicrm.org/jira/browse/CRM-19910) Drupal view + contact sub type IN query + ([424](https://github.com/civicrm/civicrm-drupal/pull/424))** + + Views was attempting to filter contact subtype as a single-value field rather + than a delimited multi-value field. + +- **[CRM-20051](https://issues.civicrm.org/jira/browse/CRM-20051) Drupal 8 user + view page, Profile information not displaying + ([428](https://github.com/civicrm/civicrm-drupal/pull/428))** + + CiviCRM's implementation of `hook_user_view()` needed to reflect a change to + the hook function signature. + +- **[CRM-19960](https://issues.civicrm.org/jira/browse/CRM-19960) Drupal 8 + Standard Page title does not immediately disappear on contact record screen + ([9770](https://github.com/civicrm/civicrm-core/pull/9770))** + +- **[CRM-19545](https://issues.civicrm.org/jira/browse/CRM-19545) Custom field + groups which do not directly extend the base 'Contact' disappear from Drupal + view after applying patch CRM-18776 + ([417](https://github.com/civicrm/civicrm-drupal/pull/417))** + + This reverts a change for + [CRM-18776](https://issues.civicrm.org/jira/browse/CRM-18776), which in turn + was attempting to fix a bug with custom fields that apply to only certain + types of an entity (e.g. activity types or financial types). That original + issue is still outstanding. + +## <a name="misc"></a>Miscellany + +- **[CRM-20154](https://issues.civicrm.org/jira/browse/CRM-20154) dedupe code + improvement, remove unused autoflip parameter + ([9893](https://github.com/civicrm/civicrm-core/pull/9893) and + [9873](https://github.com/civicrm/civicrm-core/pull/9873))** + + This cleans up code and removes a parameter called `autoFlip` that was never + fully implemented in the merging of duplicate contacts. + +- **[CRM-20181](https://issues.civicrm.org/jira/browse/CRM-20181) Deprecate + CRM_Core_Error::fatal() + ([9900](https://github.com/civicrm/civicrm-core/pull/9900))** + +- **MailingGroup API - Tighten up deprecations + ([9892](https://github.com/civicrm/civicrm-core/pull/9892))** + +- **More test output on intermittant error + ([9871](https://github.com/civicrm/civicrm-core/pull/9871))** + + A test of reverting tables now sleeps for a second. + +- **Remove mispelt param. + ([9853](https://github.com/civicrm/civicrm-core/pull/9853))** + +- **remove markdown files in /docs + ([9771](https://github.com/civicrm/civicrm-core/pull/9771))** + +- **civicrm_webtest.install - Restore access to edit message templates and tags + ([9785](https://github.com/civicrm/civicrm-core/pull/9785))** + +- **Update Test generated examples + ([9798](https://github.com/civicrm/civicrm-core/pull/9798))** + +- **[CRM-20007](https://issues.civicrm.org/jira/browse/CRM-20007) + RepeatTransaction API does not use the Payment Processor's payment Instrument + to determine Payment Instrument + ([9826](https://github.com/civicrm/civicrm-core/pull/9826))** + +## <a name="credits"></a>Credits + +This release was developed by the following code authors: + +AGH Strategies - Andrew Hunt; Australian Greens - Seamus Lee; Chanun +Chirattikanon; CiviCRM - Coleman Watts, Kurund Jalmi, Monish Deb, Tim Otten; +Francesc Bassas i Bullich; Freeform Solutions - Herb van den Dool; Fuzion - +Chris Burgess, Eileen McNaughton; Hartmann Computer Consulting - Peter Hartmann; +JMA Consulting - Edsel Lopez, Pradeep Nayak; John Kingsnorth; Lighthouse Design +and Consulting - Brian Shaughnessy; Matthew Wire; MongoDB - A. Jesse Jiryu +Davis; Sean Madsen; Semper IT - Karin Gerritsen; Skvare - Mark Hanna; Stephen +Palmstrom; Wikimedia Foundation - Eileen McNaughton + +Most authors also reviewed code for this release; in addition, the following +reviewers contributed their comments: + +Agileware - Agileware Team; Andrew Cormick-Dockery; Andrew McNaughton; Andrew +Thompson; Blackfly Solutions - Alan Dixon; Borislav Zlatanov; Circle Interactive - +Dave Jenkins; City of Winnipeg, Manitoba - Matt Allard; CiviCoop - Jaap Jansma; +CiviCRM - Jitendra Purohit, Yashodha Chaku; CiviDesk - Nicolas Ganivet, Steve +Kessler, Sunil Pawar; CompuCorp - Alessandro Verdura, Guanhuan Chen; Coop +SymbioTIC - Mathieu Lutfy, Stéphane Lussier; Davi Alexandre; Erich Schulz; +Jesper Angelo; JMA Consulting - Joe Murray, Jon Goldberg; Joinery - Allen Shaw; +Klangsoft - David Reedy Jr; Korlon - Stuart Gaston; MC3 - Graham Mitchell; +Monadnock Developmental Services - Charlie Wilder; Oxfam Germany - Thomas +Schüttler; Palante Technology Cooperative - Joseph Lacey; Progressive Technology +Project - Jamie McClelland; Skylark Technology - Owen Pearson; Spry Digital - +Ellen Hendricks; Squiffle Consulting - Aidan Saunders; Systopia - Björn Endres; +Tadpole Collective - Kevin Cristiano; Third Sector Design - Michael McAndrew; +Upleaf - Osvaldo Gomez; Vakees K; Valéry Gouleau; Veda Consulting - Kajakaran +Balakrishnan; diff --git a/civicrm/settings/Core.setting.php b/civicrm/settings/Core.setting.php index 0b35e75822059163b85573644aa6f78a5cf5e2d3..eaa0fe10fb06be172740a2d7b2d07ac458de5974 100644 --- a/civicrm/settings/Core.setting.php +++ b/civicrm/settings/Core.setting.php @@ -918,4 +918,18 @@ return array( 'description' => ts('Default to only loading matches against this number of contacts'), 'help_text' => ts('Deduping larger databases can crash the server. By configuring a limit other than 0 here the dedupe query will only search for matches against a limited number of contacts.'), ), + 'syncCMSEmail' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'syncCMSEmail', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.7', + 'title' => 'Sync CMS Email', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, then CMS email id will be syncronised with CiviCRM contacts\'s primary email.', + 'help_text' => NULL, + ), ); diff --git a/civicrm/sql/civicrm.mysql b/civicrm/sql/civicrm.mysql index 34e3ef590f70490165658595cc3d0deaced55790..f1d3a1be5aca0fcbd2d357f76dc7c38e26394805 100644 --- a/civicrm/sql/civicrm.mysql +++ b/civicrm/sql/civicrm.mysql @@ -4130,7 +4130,9 @@ CREATE TABLE `civicrm_financial_trxn` ( `status_id` int unsigned COMMENT 'pseudo FK to civicrm_option_value of contribution_status_id option_group', `payment_processor_id` int unsigned COMMENT 'Payment Processor for this financial transaction', `payment_instrument_id` int unsigned COMMENT 'FK to payment_instrument option group values', - `check_number` varchar(255) COMMENT 'Check number' + `card_type` int unsigned COMMENT 'FK to accept_creditcard option group values', + `check_number` varchar(255) COMMENT 'Check number', + `pan_truncation` int unsigned COMMENT 'Last 4 digits of credit card' , PRIMARY KEY ( `id` ) diff --git a/civicrm/sql/civicrm_data.mysql b/civicrm/sql/civicrm_data.mysql index ea344dffd9cf6b159bb58fc65eefec3f8edf7938..af17d542513c81d36fc919525cf56a4e379ca210 100644 --- a/civicrm/sql/civicrm_data.mysql +++ b/civicrm/sql/civicrm_data.mysql @@ -6290,7 +6290,7 @@ INSERT INTO civicrm_uf_field ( 10, 'receive_date', 1, 1, 4, 'User and User Admin Only', 0, 0, NULL, 'Received', 'Contribution', NULL, NULL ), ( 10, 'contribution_source', 0, 0, 5, 'User and User Admin Only', 0, 0, NULL, 'Source', 'Contribution', NULL, NULL ), ( 10, 'payment_instrument', 0, 0, 6, 'User and User Admin Only', 0, 0, NULL, 'Payment Method', 'Contribution', NULL, NULL ), - ( 10, 'check_number', 0, 0, 7, 'User and User Admin Only', 0, 0, NULL, 'Check Number', 'Contribution', NULL, NULL ), + ( 10, 'contribution_check_number', 0, 0, 7, 'User and User Admin Only', 0, 0, NULL, 'Check Number', 'Contribution', NULL, NULL ), ( 10, 'send_receipt', 0, 0, 8, 'User and User Admin Only', 0, 0, NULL, 'Send Receipt', 'Contribution', NULL, NULL ), ( 10, 'invoice_id', 0, 0, 9, 'User and User Admin Only', 0, 0, NULL, 'Invoice ID', 'Contribution', NULL, NULL ), ( 10, 'soft_credit', 0, 0, 10, 'User and User Admin Only', 0, 0, NULL, 'Soft Credit', 'Contribution', NULL, NULL ), @@ -6305,7 +6305,7 @@ INSERT INTO civicrm_uf_field ( 11, 'total_amount', 0, 1, 8, 'User and User Admin Only', 0, 0, NULL, 'Amount', 'Membership', NULL, NULL ), ( 11, 'receive_date', 1, 1, 9, 'User and User Admin Only', 0, 0, NULL, 'Received', 'Membership', NULL, NULL ), ( 11, 'payment_instrument', 0, 0, 10, 'User and User Admin Only', 0, 0, NULL, 'Payment Method', 'Membership', NULL, NULL ), - ( 11, 'check_number', 0, 0, 11, 'User and User Admin Only', 0, 0, NULL, 'Check Number', 'Membership', NULL, NULL ), + ( 11, 'contribution_check_number', 0, 0, 11, 'User and User Admin Only', 0, 0, NULL, 'Check Number', 'Membership', NULL, NULL ), ( 11, 'contribution_status_id', 1, 1, 12, 'User and User Admin Only', 0, 0, NULL, 'Payment Status', 'Membership', NULL, NULL ), ( 11, 'soft_credit', 0, 0, 13, 'User and User Admin Only', 0, 0, NULL, 'Soft Credit', 'Membership', NULL, NULL ), ( 11, 'soft_credit_type', 0, 0, 14, 'User and User Admin Only', 0, 0, NULL, 'Soft Credit Type', 'Membership', NULL, NULL ), @@ -23854,4 +23854,4 @@ INSERT INTO `civicrm_report_instance` VALUES ( @domainID, 'Survey Details', 'survey/detail', 'Detailed report for canvassing, phone-banking, walk lists or other surveys.', 'access CiviReport', 'a:39:{s:6:"fields";a:2:{s:9:"sort_name";s:1:"1";s:6:"result";s:1:"1";}s:22:"assignee_contact_id_op";s:2:"eq";s:25:"assignee_contact_id_value";s:0:"";s:12:"sort_name_op";s:3:"has";s:15:"sort_name_value";s:0:"";s:17:"street_number_min";s:0:"";s:17:"street_number_max";s:0:"";s:16:"street_number_op";s:3:"lte";s:19:"street_number_value";s:0:"";s:14:"street_name_op";s:3:"has";s:17:"street_name_value";s:0:"";s:15:"postal_code_min";s:0:"";s:15:"postal_code_max";s:0:"";s:14:"postal_code_op";s:3:"lte";s:17:"postal_code_value";s:0:"";s:7:"city_op";s:3:"has";s:10:"city_value";s:0:"";s:20:"state_province_id_op";s:2:"in";s:23:"state_province_id_value";a:0:{}s:13:"country_id_op";s:2:"in";s:16:"country_id_value";a:0:{}s:12:"survey_id_op";s:2:"in";s:15:"survey_id_value";a:0:{}s:12:"status_id_op";s:2:"eq";s:15:"status_id_value";s:1:"1";s:11:"custom_1_op";s:2:"in";s:14:"custom_1_value";a:0:{}s:11:"custom_2_op";s:2:"in";s:14:"custom_2_value";a:0:{}s:17:"custom_3_relative";s:1:"0";s:13:"custom_3_from";s:0:"";s:11:"custom_3_to";s:0:"";s:11:"description";s:75:"Detailed report for canvassing, phone-banking, walk lists or other surveys.";s:13:"email_subject";s:0:"";s:8:"email_to";s:0:"";s:8:"email_cc";s:0:"";s:10:"permission";s:17:"access CiviReport";s:6:"groups";s:0:"";s:9:"domain_id";i:1;}'); -UPDATE civicrm_domain SET version = '4.7.16'; +UPDATE civicrm_domain SET version = '4.7.17'; diff --git a/civicrm/sql/civicrm_generated.mysql b/civicrm/sql/civicrm_generated.mysql index 7ccbdf26e1d5cdba08ccdbd51a46837eae84e11e..8e692636fbc7abd19428ea1013343a7c2b6e8b1c 100644 --- a/civicrm/sql/civicrm_generated.mysql +++ b/civicrm/sql/civicrm_generated.mysql @@ -399,7 +399,7 @@ UNLOCK TABLES; LOCK TABLES `civicrm_domain` WRITE; /*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */; -INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'4.7.16',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}'); +INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'4.7.17',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}'); /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */; UNLOCK TABLES; @@ -1402,7 +1402,7 @@ UNLOCK TABLES; LOCK TABLES `civicrm_uf_field` WRITE; /*!40000 ALTER TABLE `civicrm_uf_field` DISABLE KEYS */; -INSERT INTO `civicrm_uf_field` (`id`, `uf_group_id`, `field_name`, `is_active`, `is_view`, `is_required`, `weight`, `help_post`, `help_pre`, `visibility`, `in_selector`, `is_searchable`, `location_type_id`, `phone_type_id`, `website_type_id`, `label`, `field_type`, `is_reserved`, `is_multi_summary`) VALUES (1,1,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(2,1,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(3,1,'street_address',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',0,0),(4,1,'city',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',0,0),(5,1,'postal_code',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(6,1,'country',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(7,1,'state_province',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(8,2,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(9,2,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(10,2,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(11,3,'participant_status',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Participant Status','Participant',1,0),(12,4,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(13,4,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(14,4,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(15,5,'organization_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(16,5,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(17,6,'household_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Household Name','Household',0,0),(18,6,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(19,7,'phone',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,1,NULL,'Home Phone','Contact',0,0),(20,7,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,2,NULL,'Home Mobile','Contact',0,0),(21,7,'street_address',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Address','Contact',0,0),(22,7,'city',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'City','Contact',0,0),(23,7,'state_province',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'State','Contact',0,0),(24,7,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Postal Code','Contact',0,0),(25,7,'email',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Email','Contact',0,0),(26,7,'group',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Groups','Contact',0,0),(27,7,'tag',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Tags','Contact',0,0),(28,7,'gender_id',1,0,1,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Gender','Individual',0,0),(29,7,'birth_date',1,0,1,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Date of Birth','Individual',0,0),(30,8,'street_address',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',1,0),(31,8,'city',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',1,0),(32,8,'postal_code',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(33,8,'country',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(34,8,'state_province',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(35,9,'organization_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(36,9,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,3,1,NULL,'Phone (Main) ','Contact',0,0),(37,9,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Email (Main) ','Contact',0,0),(38,9,'street_address',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Street Address','Contact',0,0),(39,9,'city',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'City','Contact',0,0),(40,9,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Postal Code','Contact',0,0),(41,9,'country',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Country','Contact',0,0),(42,9,'state_province',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'State/Province','Contact',0,0),(43,10,'financial_type',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Contribution',1,0),(44,10,'total_amount',1,0,0,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Contribution',1,0),(45,10,'contribution_status_id',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Status','Contribution',1,0),(46,10,'receive_date',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Contribution',1,0),(47,10,'contribution_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Contribution',0,0),(48,10,'payment_instrument',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Contribution',0,0),(49,10,'check_number',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Contribution',0,0),(50,10,'send_receipt',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Contribution',0,0),(51,10,'invoice_id',1,0,0,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Invoice ID','Contribution',0,0),(52,10,'soft_credit',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Contribution',0,0),(53,10,'soft_credit_type',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Contribution',0,0),(54,11,'membership_type',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Membership Type','Membership',1,0),(55,11,'join_date',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Member Since','Membership',1,0),(56,11,'membership_start_date',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Start Date','Membership',1,0),(57,11,'membership_end_date',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'End Date','Membership',1,0),(58,11,'membership_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Membership',0,0),(59,11,'send_receipt',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Membership',0,0),(60,11,'financial_type',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Membership',1,0),(61,11,'total_amount',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Membership',1,0),(62,11,'receive_date',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Membership',1,0),(63,11,'payment_instrument',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Membership',0,0),(64,11,'check_number',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Membership',0,0),(65,11,'contribution_status_id',1,0,1,12,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Status','Membership',1,0),(66,11,'soft_credit',1,0,0,13,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Membership',0,0),(67,11,'soft_credit_type',1,0,0,14,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Membership',0,0),(68,12,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(69,12,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(70,12,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(71,13,'prefix_id',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Individual Prefix','Individual',1,0),(72,13,'first_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',1,0),(73,13,'last_name',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',1,0),(74,13,'email',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Email Address','Contact',1,0); +INSERT INTO `civicrm_uf_field` (`id`, `uf_group_id`, `field_name`, `is_active`, `is_view`, `is_required`, `weight`, `help_post`, `help_pre`, `visibility`, `in_selector`, `is_searchable`, `location_type_id`, `phone_type_id`, `website_type_id`, `label`, `field_type`, `is_reserved`, `is_multi_summary`) VALUES (1,1,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(2,1,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(3,1,'street_address',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',0,0),(4,1,'city',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',0,0),(5,1,'postal_code',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(6,1,'country',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(7,1,'state_province',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(8,2,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(9,2,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(10,2,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(11,3,'participant_status',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Participant Status','Participant',1,0),(12,4,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(13,4,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(14,4,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(15,5,'organization_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(16,5,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(17,6,'household_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Household Name','Household',0,0),(18,6,'email',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(19,7,'phone',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,1,NULL,'Home Phone','Contact',0,0),(20,7,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,2,NULL,'Home Mobile','Contact',0,0),(21,7,'street_address',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Address','Contact',0,0),(22,7,'city',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'City','Contact',0,0),(23,7,'state_province',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'State','Contact',0,0),(24,7,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Postal Code','Contact',0,0),(25,7,'email',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Primary Email','Contact',0,0),(26,7,'group',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Groups','Contact',0,0),(27,7,'tag',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Tags','Contact',0,0),(28,7,'gender_id',1,0,1,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Gender','Individual',0,0),(29,7,'birth_date',1,0,1,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Date of Birth','Individual',0,0),(30,8,'street_address',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Street Address (Home)','Contact',1,0),(31,8,'city',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'City (Home)','Contact',1,0),(32,8,'postal_code',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Postal Code (Home)','Contact',0,0),(33,8,'country',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Country (Home)','Contact',0,0),(34,8,'state_province',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'State (Home)','Contact',0,0),(35,9,'organization_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Organization Name','Organization',0,0),(36,9,'phone',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,3,1,NULL,'Phone (Main) ','Contact',0,0),(37,9,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Email (Main) ','Contact',0,0),(38,9,'street_address',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Street Address','Contact',0,0),(39,9,'city',1,0,1,5,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'City','Contact',0,0),(40,9,'postal_code',1,0,1,6,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Postal Code','Contact',0,0),(41,9,'country',1,0,1,7,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'Country','Contact',0,0),(42,9,'state_province',1,0,1,8,NULL,NULL,'User and User Admin Only',0,0,3,NULL,NULL,'State/Province','Contact',0,0),(43,10,'financial_type',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Contribution',1,0),(44,10,'total_amount',1,0,0,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Contribution',1,0),(45,10,'contribution_status_id',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Status','Contribution',1,0),(46,10,'receive_date',1,0,1,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Contribution',1,0),(47,10,'contribution_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Contribution',0,0),(48,10,'payment_instrument',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Contribution',0,0),(49,10,'contribution_check_number',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Contribution',0,0),(50,10,'send_receipt',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Contribution',0,0),(51,10,'invoice_id',1,0,0,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Invoice ID','Contribution',0,0),(52,10,'soft_credit',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Contribution',0,0),(53,10,'soft_credit_type',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Contribution',0,0),(54,11,'membership_type',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Membership Type','Membership',1,0),(55,11,'join_date',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Member Since','Membership',1,0),(56,11,'membership_start_date',1,0,0,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Start Date','Membership',1,0),(57,11,'membership_end_date',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'End Date','Membership',1,0),(58,11,'membership_source',1,0,0,5,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Source','Membership',0,0),(59,11,'send_receipt',1,0,0,6,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Send Receipt','Membership',0,0),(60,11,'financial_type',1,0,0,7,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Financial Type','Membership',1,0),(61,11,'total_amount',1,0,0,8,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Amount','Membership',1,0),(62,11,'receive_date',1,0,1,9,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Received','Membership',1,0),(63,11,'payment_instrument',1,0,0,10,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Method','Membership',0,0),(64,11,'contribution_check_number',1,0,0,11,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Check Number','Membership',0,0),(65,11,'contribution_status_id',1,0,1,12,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Payment Status','Membership',1,0),(66,11,'soft_credit',1,0,0,13,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit','Membership',0,0),(67,11,'soft_credit_type',1,0,0,14,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Soft Credit Type','Membership',0,0),(68,12,'first_name',1,0,1,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',0,0),(69,12,'last_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',0,0),(70,12,'email',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Email Address','Contact',0,0),(71,13,'prefix_id',1,0,0,1,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Individual Prefix','Individual',1,0),(72,13,'first_name',1,0,1,2,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'First Name','Individual',1,0),(73,13,'last_name',1,0,1,3,NULL,NULL,'User and User Admin Only',0,0,NULL,NULL,NULL,'Last Name','Individual',1,0),(74,13,'email',1,0,0,4,NULL,NULL,'User and User Admin Only',0,0,1,NULL,NULL,'Email Address','Contact',1,0); /*!40000 ALTER TABLE `civicrm_uf_field` ENABLE KEYS */; UNLOCK TABLES; diff --git a/civicrm/templates/CRM/Admin/Form/Setting/UF.tpl b/civicrm/templates/CRM/Admin/Form/Setting/UF.tpl index 77f245749be9dcadfe5480ecee5c650dc8e02d87..a38feec15b701043829a8d89355457b2608e0b87 100644 --- a/civicrm/templates/CRM/Admin/Form/Setting/UF.tpl +++ b/civicrm/templates/CRM/Admin/Form/Setting/UF.tpl @@ -41,6 +41,10 @@ </td> </tr> {/if} + <tr class="crm-uf-form-block-syncCMSEmail"> + <td class="label">{$form.syncCMSEmail.label}</td> + <td>{$form.syncCMSEmail.html}</td> + </tr> </table> <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div> <div class="spacer"></div> diff --git a/civicrm/templates/CRM/Admin/Page/APIExplorer.js b/civicrm/templates/CRM/Admin/Page/APIExplorer.js index bbcc7260954dd8483fe76dd8de9c054ae9090dd1..aa871e76839a403cf86b05696b8a6ca5dc43a09f 100644 --- a/civicrm/templates/CRM/Admin/Page/APIExplorer.js +++ b/civicrm/templates/CRM/Admin/Page/APIExplorer.js @@ -20,8 +20,7 @@ docCodeTpl = _.template($('#doc-code-tpl').html()), joinTpl = _.template($('#join-tpl').html()), - // The following apis do not support the syntax for joins - // FIXME: the solution is to convert these apis to use _civicrm_api3_basic_get + // The following apis do not use Api3SelectQuery so do not support advanced features like joins or OR NO_JOINS = ['Contact', 'Contribution', 'Pledge', 'Participant'], // These types of entityRef don't require any input to open @@ -134,9 +133,10 @@ function addJoinInfo(field, name) { if (field.name === 'entity_id') { - var entityTableParam = name.slice(0, -2) + 'table'; - if (params[entityTableParam]) { - field.FKApiName = getField(entityTableParam).options[params[entityTableParam]]; + var entityTableParam = name.slice(0, -2) + 'table', + entityField = params[entityTableParam] ? getField(entityTableParam) : {}; + if (entityField.options) { + field.FKApiName = entityField.options[params[entityTableParam]]; } } if (field.pseudoconstant && field.pseudoconstant.optionGroupName) { @@ -660,6 +660,7 @@ } }); if (entity && action) { + handleAndOr(); formatQuery(); } } @@ -879,14 +880,14 @@ */ function renderJoinSelector() { $('#api-join').hide(); - if (!_.includes(NO_JOINS, entity) && _.includes(['get', 'getsingle'], action)) { + if (!_.includes(NO_JOINS, entity) && _.includes(['get', 'getsingle', 'getcount'], action)) { var joinable = {}; (function recurse(fields, joinable, prefix, depth, entities) { _.each(fields, function(field) { var name = prefix + field.name; addJoinInfo(field, name); var entity = field.FKApiName; - if (entity) { + if (entity && (field.is_core_field || field.supports_joins)) { joinable[name] = { title: field.title + ' (' + field.FKApiName + ')', entity: entity, @@ -938,6 +939,40 @@ } } + function handleAndOr() { + if (!_.includes(NO_JOINS, entity) && _.includes(['get', 'getsingle', 'getcount'], action)) { + var or = []; + $('tr.api-param-row').each(function() { + if ($(this).next().is('tr.api-param-row') && $('input.api-param-name', this).val()) { + $('.api-and-or', this).show(); + } else { + $(this).removeClass('or').find('.api-and-or').hide(); + } + }); + $('tr.api-param-row.or').each(function() { + var val = $(this).next().find('input.api-param-name').val(); + if (val) { + if ($(this).prev().is('.or')) { + or[or.length - 1].push(val); + } else { + or.push([$('input.api-param-name', this).val(), val]); + } + } + }); + if (or.length) { + params.options = params.options || {}; + params.options.or = or; + } + } else { + $('.api-and-or').hide(); + } + } + + function toggleAndOr() { + $(this).closest('tr').toggleClass('or'); + buildParams(); + } + $(document).ready(function() { // Set up tabs - bind active tab to document hash because... it's cool? document.location.hash = document.location.hash || 'explorer'; @@ -996,7 +1031,13 @@ $(this).closest('tr').remove(); buildParams(); }) - .on('change', 'select.api-chain-entity', getChainedAction); + .on('click', '.api-and-or > span', toggleAndOr) + .on('change', 'select.api-chain-entity', getChainedAction) + .on('sortupdate', buildParams) + .sortable({ + handle: '.api-sort-handle', + items: '.api-chain-row, .api-param-row' + }); $('#api-join').on('change', 'input', onSelectJoin); $('#example-entity').on('change', getExamples); $('#example-action').on('change', getExample); diff --git a/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl b/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl index fea4a10bcd9224eec877e9a6711bf5535f27f2cc..b2b22bbc87de9f7ae8740721e31f8da081e65c89 100644 --- a/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl +++ b/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl @@ -50,6 +50,9 @@ margin-top: 1em; overflow: auto; } + #api-params tr td { + padding-top: 13px; + } #api-params-table th:first-child, #api-params-table td:first-child { width: 35%; @@ -69,6 +72,61 @@ #api-params-table th:first-child + th + th { width: 65% } + #api-params .api-sort-handle { + margin-right: 10px; + cursor: move; + } + #api-params tr td > .crm-i, + #api-params tr td > a .crm-i { + color: lightgrey; + } + #api-params tr:hover td > .crm-i, + #api-params tr:hover td > a .crm-i { + color: grey; + } + #api-params .api-and-or { + margin-left: 1.2em; + font-size: .8em; + position: relative; + top: 5px; + width: 10em; + margin-bottom: -9px; + } + #api-params .api-and-or > span { + padding: 0 1em; + background: white; + cursor: pointer; + } + #api-params .api-or, + #api-params tr.or .api-and { + color: lightgrey; + } + #api-params tr.or .api-or { + color: inherit; + } + #api-params .api-and-or .crm-i { + transform: rotate(180deg); + } + #api-params tr.or .api-and-or .crm-i { + transform: initial; + } + #api-params .api-and-or:hover .crm-i { + color: #2786c2; + } + #api-params tr.or { + border-top: 3px solid lightgrey; + border-left: 3px solid lightgrey; + border-right: 3px solid lightgrey; + } + #api-params tr.or + tr { + border-left: 3px solid lightgrey; + border-right: 3px solid lightgrey; + border-bottom: 3px solid lightgrey; + } + #api-params tr.or + tr.or { + border-top: none; + border-bottom: none; + } #api-generated td:first-child { width: 60px; } @@ -171,13 +229,13 @@ <div id="mainTabContainer"> <ul> <li class="ui-corner-all" title="GUI to build and execute API calls"> - <a href="#explorer-tab">{ts}Explorer{/ts}</a> + <a href="#explorer-tab"><i class="crm-i fa-search"></i> {ts}Explorer{/ts}</a> </li> <li class="ui-corner-all" title="Auto-generated examples from the test suite"> - <a href="#examples-tab">{ts}Examples{/ts}</a> + <a href="#examples-tab"><i class="crm-i fa-book"></i> {ts}Examples{/ts}</a> </li> <li class="ui-corner-all" title="API source-code and code-level documentation"> - <a href="#docs-tab">{ts}Code Docs{/ts}</a> + <a href="#docs-tab"><i class="crm-i fa-code"></i> {ts}Code Docs{/ts}</a> </li> </ul> @@ -303,7 +361,11 @@ {strip} <script type="text/template" id="api-param-tpl"> <tr class="api-param-row"> - <td><input style="width: 100%;" class="crm-form-text api-param-name api-input" value="<%= name %>" placeholder="{ts}Parameter{/ts}" /></td> + <td> + <i class="crm-i api-sort-handle fa-arrows"></i> + <input style="width: 90%;" class="crm-form-text api-param-name api-input" value="<%= name %>" placeholder="{ts}Parameter{/ts}" /> + <div class="api-and-or"><span><span class="api-and">{ts}AND{/ts}</span> <i class="crm-i fa-toggle-on"></i> <span class="api-or">{ts}OR{/ts}</span></span></div> + </td> <td> {literal} <% if (noOps) { %> @@ -357,7 +419,8 @@ <script type="text/template" id="api-chain-tpl"> <tr class="api-chain-row"> <td> - <select style="width: 100%;" class="crm-form-select api-chain-entity"> + <i class="crm-i api-sort-handle fa-arrows"></i> + <select style="width: 90%;" class="crm-form-select api-chain-entity"> <option value=""></option> {foreach from=$entities.values item=entity} <option value="{$entity}" {if !empty($entities.deprecated) && in_array($entity, $entities.deprecated)}class="strikethrough"{/if}> diff --git a/civicrm/templates/CRM/Batch/Form/Entry.js b/civicrm/templates/CRM/Batch/Form/Entry.js index 23bf05aef91fc5a6d28fd5afd781384bade9d809..89fcda8db49bf648e2fd1ad93b2f964b6b460a26 100644 --- a/civicrm/templates/CRM/Batch/Form/Entry.js +++ b/civicrm/templates/CRM/Batch/Form/Entry.js @@ -171,6 +171,7 @@ function checkColumns(parentRow) { parentRow.find('div .required').each(function () { //special case to handle contact autocomplete select + // @todo WHY OH WHY is this duplicated on the tpl file? var fieldId = cj(this).attr('id'); if (fieldId.substring(0, 16) == 'primary_contact_') { // if display value is set then make sure we also check if contact id is set diff --git a/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl b/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl index 289058760b3e92437780b7e35de7804a97ea1d70..e42247fa94d6c5dc2989a8ace180e631ea9276bf 100644 --- a/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl +++ b/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl @@ -328,7 +328,7 @@ var surveyActivityIds = {/literal}{$surveyActivityIds}{literal}; if (interview.errors[error]) errorList = errorList + '<li>' + interview.errors[error] + '</li>'; } if ( errorList ) { - var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red"></i> ' + ts('Please correct the following errors in the survey fields below:') + '<ul>' + errorList + '</ul>'; + var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red"></i> {/literal}{ts}Please correct the following errors in the survey fields below:{/ts}{literal}<ul>' + errorList + '</ul>'; CRM.$('#responseErrors').show( ).html(allErrors); } } diff --git a/civicrm/templates/CRM/Contact/Form/Merge.tpl b/civicrm/templates/CRM/Contact/Form/Merge.tpl index 4541877abfcd0e0b5976a9a8bcf14de24ff2310d..ca2de4c87ad5302fc901725ae452550a289a5d93 100644 --- a/civicrm/templates/CRM/Contact/Form/Merge.tpl +++ b/civicrm/templates/CRM/Contact/Form/Merge.tpl @@ -130,9 +130,22 @@ $row.title|substr:0:5 == "Phone"} <td> - {* @TODO check if this is ever an array or a fileName? *} - {* This is on one long line for address formatting *} - {if $row.title|substr:0:7 == "Address"}<span style="white-space: pre" id="main_{$blockName}_{$blockId}">{else}<span id="main_{$blockName}_{$blockId}">{/if}{if !is_array($row.main)}{$row.main}{elseif $row.main.fileName}{$row.main.fileName}{else}{', '|implode:$row.main}{/if}</span> + {strip} + {if $row.title|substr:0:7 == "Address"} + <span style="white-space: pre" id="main_{$blockName}_{$blockId}"> + {else} + <span id="main_{$blockName}_{$blockId}"> + {/if} + {* @TODO check if this is ever an array or a fileName? *} + {if !is_array($row.main)} + {$row.main} + {elseif $row.main.fileName} + {$row.main.fileName} + {else} + {', '|implode:$row.main} + {/if} + </span> + {/strip} </td> <td> @@ -220,10 +233,6 @@ {/if} {/foreach} </table> - <div class='form-item'> - <!--<p>{$form.moveBelongings.html} {$form.moveBelongings.label}</p>--> - <!--<p>{$form.deleteOther.html} {$form.deleteOther.label}</p>--> - </div> <div class="crm-submit-buttons"> {include file="CRM/common/formButtons.tpl" location="bottom"} @@ -239,7 +248,7 @@ /** * Triggered when a 'location' or 'type' destination is changed, and when * the operation or 'set primary' checkboxes are changed. - * + * * Check to see if the 'main' contact record has a corresponding location * block when the destination of a field is changed. Allow existing location * fields to be overwritten with data from the 'other' contact. @@ -388,29 +397,26 @@ } } - CRM.$(function($) { - - $('table td input.form-checkbox').each(function() { - var ele = null; - var element = $(this).attr('id').split('_',3); + /** + * Toggle the location type and the is_primary on & off depending on whether the merge box is ticked. + * + * @param element + */ + function toggleRelatedLocationFields(element) { + relatedElements = CRM.$(element).parent().siblings('td').find('input,select,label,hidden'); + if (CRM.$(element).is(':checked')) { + relatedElements.removeClass('disabled').attr('disabled', false); - switch ( element['1'] ) { - case 'addressee': - ele = '#' + element['0'] + '_' + element['1']; - break; + } + else { + relatedElements.addClass('disabled').attr('disabled', true); + } - case 'email': - case 'postal': - ele = '#' + element['0'] + '_' + element['1'] + '_' + element['2']; - break; - } + } - if( ele ) { - $(this).on('click', function() { - var val = $(this).prop('checked'); - $('input' + ele + ', input' + ele + '_custom').prop('checked', val); - }); - } + CRM.$(function($) { + $('input.crm-form-checkbox[data-is_location]').on('click', function(){ + toggleRelatedLocationFields(this) }); // Show/hide matching data rows @@ -419,6 +425,8 @@ }); // Call mergeBlock whenever a location type is changed + // (This is applied to the body because the inputs can be added dynamically + // to the form, and we need to catch when they change.) $('body').on('change', 'select[id$="locTypeId"],select[id$="typeTypeId"],input[id$="[operation]"],input[id$="[set_other_primary]"]', function(event){ // All the information we need is held in the id, separated by underscores diff --git a/civicrm/templates/CRM/Event/Form/EventFees.tpl b/civicrm/templates/CRM/Event/Form/EventFees.tpl index e481c82a84883d2a47cfe146debe55b44ec9d728..002f24e41b98c0c19c46c38ffb1737dc3cef4722 100644 --- a/civicrm/templates/CRM/Event/Form/EventFees.tpl +++ b/civicrm/templates/CRM/Event/Form/EventFees.tpl @@ -24,13 +24,6 @@ +--------------------------------------------------------------------+ *} {assign var=isRecordPayment value=1 } -{if $isFTPermissionDenied} - <script> - {literal} - CRM.alert(ts('You do not have all the permissions needed for this page.'), 'Permission Denied', 'error'); - {/literal} - </script> -{/if} {if $paid} {* We retrieve this tpl when event is selected - keep it empty if event is not paid *} <table class="form-layout"> {if $priceSet} diff --git a/civicrm/templates/CRM/Event/Form/SelfSvcUpdate.tpl b/civicrm/templates/CRM/Event/Form/SelfSvcUpdate.tpl index 746a65f7a8309b9c1a5a49ad93592c2937c9ac66..6792392148a3c153c0328f5965096a770386f721 100644 --- a/civicrm/templates/CRM/Event/Form/SelfSvcUpdate.tpl +++ b/civicrm/templates/CRM/Event/Form/SelfSvcUpdate.tpl @@ -56,7 +56,7 @@ $('#action').on('change', function() { selected = $(this).find("option:selected").text(); if (selected == 'Cancel' && contributionID) { - CRM.alert(ts('Cancellations are not refundable.'), 'Warning', 'alert'); + CRM.alert('{/literal}{ts}Cancellations are not refundable.{/ts}{literal}', 'Warning', 'alert'); } }); }); diff --git a/civicrm/templates/CRM/Price/Page/LineItem.tpl b/civicrm/templates/CRM/Price/Page/LineItem.tpl index 9c0c0f365cbf06265ebc7def7638e3b90ea8d4e8..d0ab3de21c18ec8cbd3ceb322087796ac0961449 100644 --- a/civicrm/templates/CRM/Price/Page/LineItem.tpl +++ b/civicrm/templates/CRM/Price/Page/LineItem.tpl @@ -78,7 +78,7 @@ {if $getTaxDetails} <td class="right">{$line.line_total|crmMoney}</td> {if $line.tax_rate != "" || $line.tax_amount != ""} - <td class="right">{$taxTerm} ({$line.tax_rate|string_format:"%.2f"}%)</td> + <td class="right">{$taxTerm} ({$line.tax_rate|string_format:"%.3f"}%)</td> <td class="right">{$line.tax_amount|crmMoney}</td> {else} <td></td> diff --git a/civicrm/templates/CRM/Tag/Form/Edit.tpl b/civicrm/templates/CRM/Tag/Form/Edit.tpl index 646dd7c519eb06770131d62721b8de4e0dfd8f8b..0f78e0f83936a206f5d9abed54bbd664ec8ff788 100644 --- a/civicrm/templates/CRM/Tag/Form/Edit.tpl +++ b/civicrm/templates/CRM/Tag/Form/Edit.tpl @@ -42,6 +42,7 @@ <td>{$form.parent_id.html}</td> </tr> {/if} + {if $form.used_for} <tr class="crm-tag-form-block-used_for"> <td class="label">{$form.used_for.label}</td> <td>{$form.used_for.html} <br /> @@ -52,6 +53,7 @@ </span> </td> </tr> + {/if} {if $form.color.html} <tr class="crm-tag-form-block-color"> <td class="label">{$form.color.label}</td> @@ -81,7 +83,7 @@ </table><br /> {/if} {else} - <div class="status">{ts 1=$delName}Are you sure you want to delete <b>%1</b> Tag?{/ts}<br />{ts}This tag will be removed from any currently tagged contacts, and users will no longer be able to assign contacts to this tag.{/ts}</div> + <div class="status">{ts 1=$delName}Are you sure you want to delete <b>%1</b>?{/ts}<br />{ts}This tag will be removed from any currently tagged contacts, and users will no longer be able to assign contacts to this tag.{/ts}</div> {/if} <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div> </div> @@ -90,8 +92,9 @@ CRM.$(function($) { var $form = $('form.{/literal}{$form.formClass}{literal}'); function toggleUsedFor() { - $('.crm-tag-form-block-used_for', $form).toggle(!$(this).val()); - if ($(this).val()) { + var value = $(this).val() && $(this).val() !== '0'; + $('.crm-tag-form-block-used_for', $form).toggle(!value); + if (value) { $('select#used_for', $form).val('').change(); } } diff --git a/civicrm/templates/CRM/Tag/Form/Merge.tpl b/civicrm/templates/CRM/Tag/Form/Merge.tpl new file mode 100644 index 0000000000000000000000000000000000000000..a62e200a16d6cd6582dcd646cf523ddebf56af77 --- /dev/null +++ b/civicrm/templates/CRM/Tag/Form/Merge.tpl @@ -0,0 +1,39 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2017 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM 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 and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +{* this template is used for merging tags (admin) *} +<div class="crm-block crm-form-block crm-tag-form-block"> + <div class="status"> + {ts 1=$tags|@count}You are about to combine the following %1 tags into a single tag:{/ts}<br /> + {', '|implode:$tags} + </div> + <table class="form-layout-compressed"> + <tr class="crm-tag-form-block-label"> + <td class="label">{$form.name.label}</td> + <td>{$form.name.html}</td> + </tr> + </table> + <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div> +</div> \ No newline at end of file diff --git a/civicrm/templates/CRM/Tag/Form/Tag.tpl b/civicrm/templates/CRM/Tag/Form/Tag.tpl index 817fdddba812f83811d0778860ac36ca7c5e740e..b83dffad9c17bf0415bfc90a1e5c82326997d8b0 100644 --- a/civicrm/templates/CRM/Tag/Form/Tag.tpl +++ b/civicrm/templates/CRM/Tag/Form/Tag.tpl @@ -25,19 +25,6 @@ *} {* this template is used for adding/editing tags *} {literal} -<style> - #tagtree, - #tagtree li.highlighted ul { - background-color: white; - } - #tagtree li.highlighted, - #tagtree li.highlighted-child.jstree-closed { - background-color: #fefcb0; - } - #tagtree ins.jstree-icon { - cursor: pointer; - } -</style> <script type="text/javascript"> (function($, _){{/literal} var entityID={$entityID}, @@ -46,7 +33,7 @@ {literal} CRM.updateContactSummaryTags = function() { var tags = []; - $('#tagtree input:checkbox:checked+span label').each(function() { + $('#tagtree input:checkbox:checked+a label').each(function() { tags.push('<span class="crm-tag-item" style="' + $(this).attr('style') + '" title="' + ($(this).attr('title') || '') + '">' + $(this).text() + '</span>'); }); $('input.crm-contact-tagset').each(function() { @@ -83,8 +70,12 @@ if (childTag) { //load js tree. $("#tagtree").jstree({ - plugins : ["themes", "html_data"], + plugins : ["themes", "html_data", "search"], core: {animation: 100}, + 'search': { + 'case_insensitive' : true, + 'show_only_matches': true + }, themes: { "theme": 'classic', "dots": false, @@ -102,15 +93,37 @@ {literal} $(document).on('change', 'input.crm-contact-tagset', CRM.updateContactSummaryTags); + + $('input[name=filter_tag_tree]', '#Tag').on('keyup change', function() { + $("#tagtree").jstree('search', $(this).val()); + }); }); })(CRM.$, CRM._); {/literal} </script> <div id="Tag" class="view-content"> - <h3>{if !$hideContext}{ts}Tags{/ts}{/if}</h3> - <div id="tagtree"> - {include file="CRM/Tag/Form/Tagtree.tpl" level=1} - </div> - <br /> -{include file="CRM/common/Tagset.tpl"} + <table class=""> + <thead> + <tr> + <th>{ts}Tag Tree{/ts}</th> + {if $tagsetInfo.contact}<th>{ts}Tag Sets{/ts}</th>{/if} + </tr> + </thead> + <tbody> + <tr> + <td> + <input class="crm-form-text big" name="filter_tag_tree" placeholder="{ts}Filter List{/ts}" allowclear="1"/> + <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a> + <div id="tagtree"> + {include file="CRM/Tag/Form/Tagtree.tpl" level=1} + </div> + </td> + {if $tagsetInfo.contact} + <td> + {include file="CRM/common/Tagset.tpl"} + </td> + {/if} + </tr> + </tbody> + </table> </div> diff --git a/civicrm/templates/CRM/Tag/Form/Tagtree.tpl b/civicrm/templates/CRM/Tag/Form/Tagtree.tpl index 8102dabb924046e61ee91f96388ce645137e202b..5c27022c2a7b5ad714f36a05a7a612ad01057d82 100644 --- a/civicrm/templates/CRM/Tag/Form/Tagtree.tpl +++ b/civicrm/templates/CRM/Tag/Form/Tagtree.tpl @@ -28,11 +28,11 @@ {foreach from=$tree item="node" key="id"} <li id="tag_{$id}"> <input name="tagList[{$id}]" id="check_{$id}" type="checkbox" {if $node.is_selectable EQ 0}disabled=""{/if} {if $tagged[$id]}checked="checked"{/if}/> - <span> + <a> <label for="check_{$id}" id="tagLabel_{$id}" class="crm-tag-item" {if !empty($allTags.$id.color)}style="background-color: {$allTags.$id.color}; color: {$allTags.$id.color|colorContrast};"{/if} title="{$node.description}"> {$node.name} </label> - </span> + </a> {if $node.children} {* Recurse... *} {include file="CRM/Tag/Form/Tagtree.tpl" tree=$node.children level=$level+1} diff --git a/civicrm/templates/CRM/Tag/Page/Tag.tpl b/civicrm/templates/CRM/Tag/Page/Tag.tpl index dd292d70b94bd6b980d5a9392d46c545f1c80a1b..a5fc9c91d8318ec05952739d09969efe0fbc1b73 100644 --- a/civicrm/templates/CRM/Tag/Page/Tag.tpl +++ b/civicrm/templates/CRM/Tag/Page/Tag.tpl @@ -23,204 +23,510 @@ | see the CiviCRM license FAQ at http://civicrm.org/licensing | +--------------------------------------------------------------------+ *} +<div class="crm-content-block"> + <div class="help"> + {ts 1=', '|implode:$usedFor}Tags are a convenient way to categorize data (%1).{/ts} + {if call_user_func(array('CRM_Core_Permission','check'), 'administer Tagsets')} + <br /> + {ts}Create predefined tags in the main tree, or click the <strong>+</strong> to add a set for free tagging.{/ts} + {/if} + {docURL page="user/organising-your-data/groups-and-tags"} + </div> -{capture assign=docLink}{docURL page="user/organising-your-data/groups-and-tags"}{/capture} - -{if $action eq 1 or $action eq 2 or $action eq 8} - {include file="CRM/Tag/Form/Edit.tpl"} -{else} - <div class="crm-content-block"> - <div class="help"> - {ts 1=$docLink}Tags can be assigned to any contact record, and are a convenient way to find contacts. You can create as many tags as needed to organize and segment your records.{/ts} {$docLink} - </div> - - {if $rows} - <div id="mainTabContainer"> - <ul> - <li class="ui-corner-all crm-tab-button"> - <a href="#tags">{ts}Tags{/ts}</a> - </li> - <li class="ui-corner-all crm-tab-button"> - <a href="#tagsets">{ts}Tag Sets{/ts}</a> - </li> - </ul> - <div id="tags"> - {if !($action eq 1 and $action eq 2)} - <div class="crm-submit-buttons"> - <div class="action-link"> - {crmButton q="action=add&reset=1" id="newTag" icon="plus-circle"}{ts}Add Tag{/ts}{/crmButton} - </div> - </div> - {/if} - {strip} - <table id="tags_table" class="display"> - <thead> - <tr> - <th>{ts}Tag{/ts}</th> - <th>{ts}ID{/ts}</th> - <th id="nosort">{ts}Description{/ts}</th> - <th>{ts}Parent (ID){/ts}</th> - <th>{ts}Used For{/ts}</th> - <th>{ts}Reserved?{/ts}</th> - <th></th> - </tr> - </thead> - {foreach from=$rows item=row key=id } - {if !$row.is_tagset && !$row.is_tagset_child} - <tr class="{if $row.parent_id}child-row{/if} {if $row.grandparent_id}grandchild-row{/if} crm-tag crm-entity" id="tag-{$row.id}"> - <td class="crm-tag-name crm-editable crmf-name" {if $row.color}style="background-color: {$row.color}; color: {$row.color|colorContrast};"{/if}> - {$row.name} - </td> - <td class="crm-tag-id">{$row.id}</td> - <td class="crm-tag-description crm-editable crmf-description">{$row.description} </td> - <td class="crm-tag-parent">{$row.parent}{if $row.parent_id} ({$row.parent_id}){/if}</td> - <td class="crm-tag-used_for">{$row.used_for}</td> - <td class="crm-tag-is_reserved">{if $row.is_reserved}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Reserved{/ts}" />{/if}</td> - <td>{$row.action|replace:'xx':$row.id}</td> - </tr> - {/if} - {/foreach} - </table> - {/strip} - </div> - <div id="tagsets"> - {if !($action eq 1 and $action eq 2) && $adminTagSet} - <div class="crm-submit-buttons"> - <div class="action-link"> - {crmButton q="action=add&reset=1&tagset=1" id="newTagSet" icon="plus-circle"}{ts}Add Tag Set{/ts}{/crmButton} - </div> - </div> - {/if} - {strip} - <table id="tagsets_table" class="display"> - <thead> - <tr> - <th>{ts}Tag{/ts}</th> - <th>{ts}ID{/ts}</th> - <th id="nosort">{ts}Description{/ts}</th> - <th>{ts}Parent (ID){/ts}</th> - <th>{ts}Used For{/ts}</th> - <th>{ts}Reserved?{/ts}</th> - <th></th> - </tr> - </thead> - {foreach from=$rows item=row key=id} - {if $row.is_tagset || $row.is_tagset_child} - <tr class="{if $row.parent_id}child-row{/if} crm-tag crm-entity" id="tag-{$row.id}"> - <td class="crm-tag-name crm-editable crmf-name" {if $row.color}style="background-color: {$row.color}; color: {$row.color|colorContrast};"{/if}> - {$row.name} - </td> - <td class="crm-tag-id">{$row.id}</td> - <td class="crm-tag-description crm-editable crmf-description">{$row.description} </td> - <td class="crm-tag-parent">{$row.parent}{if $row.parent_id} ({$row.parent_id}){/if}</td> - <td class="crm-tag-used_for">{$row.used_for}</td> - <td class="crm-tag-is_reserved">{if $row.is_reserved}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Reserved{/ts}" />{/if}</td> - <td>{$row.action|replace:'xx':$row.id}</td> - </tr> - {/if} - {/foreach} - </table> - {/strip} - </div> - </div> - {if !($action eq 1 and $action eq 2)} - <div class="crm-submit-buttons"> - <div class="action-link"> - {crmButton q="action=add&reset=1" id="newTag" icon="plus-circle"}{ts}Add Tag{/ts}{/crmButton} - {if $adminTagSet} - {crmButton q="action=add&reset=1&tagset=1" id="newTagSet" icon="plus-circle"}{ts}Add Tag Set{/ts}{/crmButton} - {/if} - </div> - </div> + <div id="mainTabContainer"> + <ul> + <li class="ui-corner-all crm-tab-button" title="{ts}Main Tag List{/ts}"> + <a href="#tree"><i class="crm-i fa-tags"></i> {ts}Tag Tree{/ts}</a> + </li> + {foreach from=$tagsets item=set} + <li class="ui-corner-all crm-tab-button {if ($set.is_reserved)}is-reserved{/if}" title="{ts 1=', '|implode:$set.used_for_label}Tag Set for %1{/ts}"> + <a href="#tagset-{$set.id}">{$set.name}</a> + </li> + {/foreach} + {if call_user_func(array('CRM_Core_Permission','check'), 'administer Tagsets')} + <li class="ui-corner-all crm-tab-button" title="{ts}Add Tag Set{/ts}"> + <a href="#new-tagset"><i class="crm-i fa-plus"></i></a> + </li> {/if} - <div id="merge_tag_status"></div> - {include file="CRM/common/jsortable.tpl"} - {else} - <div class="messages status no-popup"> - <div class="icon inform-icon"></div> - {capture assign=crmURL}{crmURL p='civicrm/tag' q="action=add&reset=1"}{/capture} - {ts 1=$crmURL}There are no Tags present. You can <a href='%1'>add one</a>.{/ts} + </ul> + <div id="tree"> + <div class="help"> + {ts}Organize the tag hierarchy by clicking and dragging. Shift-click to select multiple tags to merge/move/delete.{/ts} </div> - {/if} - + </div> + {foreach from=$tagsets item=set} + <div id="tagset-{$set.id}"> + </div> + {/foreach} + <div id="new-tagset"> + </div> </div> - +</div> +{crmAPI entity="Contact" action="getsingle" var="user" return='display_name' id="user_contact_id"} {literal} - <script type="text/javascript"> - CRM.$(function($) { - var tag; - $('#mainTabContainer').tabs(); - $('.merge_tag').click(function(e) { - tag = $(this).crmEditableEntity(); - mergeTagDialog(); - e.preventDefault(); - }); +<script type="text/javascript"> + (function($, _) { + $(function($) { + var $window = $(window), + renderedTabs = ['tree'], + tagSets = {/literal}{$tagsets|@json_encode}{literal}, + user = {/literal}{$user|@json_encode}{literal}, + usedFor = {/literal}{$usedFor|@json_encode}{literal}, + menuHeight = $('#civicrm-menu').height() + 15, + noneSelectedTpl = _.template($('#noneSelectedTpl').html()), + oneSelectedTpl = _.template($('#oneSelectedTpl').html()), + moreSelectedTpl = _.template($('#moreSelectedTpl').html()), + tagsetHelpTpl = _.template($('#tagsetHelpTpl').html()); - function mergeTagDialog() { - var tagUrl = {/literal}"{crmURL p='civicrm/ajax/mergeTagList' h=0}"{literal}; - var title = {/literal}'{ts escape="js" 1="%1"}Merge tag %1 into:{/ts}'{literal}; - CRM.confirm({ - title: ts(title, {1: tag.name}), - message: '<input name="select_merge_tag" class="big" />', - open: function() { - var dialog = this; - $('input[name=select_merge_tag]', dialog) - .crmSelect2({ - placeholder: {/literal}'{ts escape="js"}- select tag -{/ts}'{literal}, - minimumInputLength: 1, - ajax: { - url: tagUrl, - data: function(term) { - return {term: term, fromId: tag.id}; - }, - results: function(response) { - return {results: response}; - } - } - }) - .change(function() { - $('.messages', dialog).remove(); - if ($(this).val() && $(this).select2('data').warning) { - $(dialog).append('<div class="messages status">{/literal}{ts escape='js'}Note: the selected tag is used by additional entities.{/ts}{literal}</div>'); - } - }); - } + function formatTagSet(info) { + info.date = CRM.utils.formatDate(info.created_date); + info.used_for_label = []; + if (undefined !== info.used_for) { + _.each(info.used_for.split(','), function(item) { + info.used_for_label.push(usedFor[item]); + }); + } + } + + _.each(tagSets, formatTagSet); + + function renderTree($panel) { + var plugins, + selected = [], + tagset = $panel.attr('id').split('-')[1] || 0; + + function hasChildren(id) { + var $node = $('.tag-tree', $panel).jstree(true).get_node(id, true); + return !$node.hasClass('jstree-leaf'); + } + + function changeColor() { + var color = $(this).val().toLowerCase(), + id = $(this).closest('.crm-entity').data('id'), + node = $('.tag-tree', $panel).jstree(true).get_node(id); + if (color === '#ffffff') { + node.a_attr.style = ''; + } else { + node.a_attr.style = 'background-color: ' + color + '; color: ' + CRM.utils.colorContrast(color) + ';'; + } + node.data.color = color; + $('.tag-tree', $panel).jstree(true).redraw(true); + CRM.api3('Tag', 'create', {id: id, color: color}, true); + } + + function changeSelection(e, data) { + var tplParams = { + tagset: tagset, + tagsetCount: _.keys(tagSets).length, + adminReserved: CRM.checkPerm('administer reserved tags') + }, + tree = $('.tag-tree', $panel).jstree(true), + $infoBox = $('.tag-info', $panel); + selected = data.selected; + if (!data.selected || !data.selected.length) { + tplParams.is_reserved = tagset ? tagSets[tagset].is_reserved == 1 : false; + tplParams.length = $('.tag-tree li', $panel).length; + tplParams.adminTagsets = CRM.checkPerm('administer Tagsets'); + $infoBox.html(noneSelectedTpl(tplParams)); + } else if (data.selected.length === 1) { + tplParams.usedFor = usedFor; + tplParams.hasChildren = hasChildren(data.node.id); + $infoBox.html(oneSelectedTpl($.extend({}, data.node, tplParams))); + } else { + tplParams.items = data.selected; + tplParams.hasChildren = tplParams.reserved = tplParams.usages = 0; + _.each(data.selected, function(id) { + var node = tree.get_node(id); + tplParams.usages += node.data.usages; + tplParams.reserved += node.data.is_reserved; + tplParams.hasChildren += hasChildren(id) ? 1 : 0; + }); + $infoBox.html(moreSelectedTpl(tplParams)); + } + $infoBox.trigger('crmLoad'); + } + + function clearSelection(e) { + e.preventDefault(); + $('.tag-tree', $panel).jstree(true).deselect_all(); + } + + function changeUsedFor() { + var vals = $('input[name=used_for]:checked', $panel).map(function(i, el) { + return $(el).val(); + }).get(), + id = $(this).closest('.crm-entity').data('id'); + if (vals.length) { + CRM.api3('Tag', 'create', {id: id, used_for: vals}, true); + var node = $('.tag-tree', $panel).jstree(true).get_node(id); + node.data.used_for = vals; + } + } + + function moveTag(e, data) { + if (data.parent != data.old_parent) { + CRM.api3('Tag', 'create', {id: data.node.id, parent_id: data.parent.replace('#', '')}, true); + } + } + + function deleteTagset() { + $('#mainTabContainer').tabs('option', 'active', 0); + $panel.off().remove(); + $("a[href='#tagset-" + tagset + "']").parent().remove(); + $('#mainTabContainer').tabs('refresh'); + } + + function updateTagset(info) { + tagSets[tagset].description = info.description; + tagSets[tagset].name = info.name; + tagSets[tagset].used_for = info.used_for; + tagSets[tagset].is_reserved = info.is_reserved; + formatTagSet(tagSets[tagset]); + $('.help', $panel).remove(); + addHelp(); + } + + function addHelp() { + $panel.prepend(tagsetHelpTpl(tagSets[tagset])); + $("a[href='#tagset-" + tagset + "']").text(tagSets[tagset].name) + .parent().toggleClass('is-reserved', tagSets[tagset].is_reserved == 1) + .attr('title', ts('{/literal}{ts escape='js' 1='%1'}Tag Set for %1{/ts}{literal}', {'1': tagSets[tagset].used_for_label.join(', ')})); + } + + if (tagset) { + addHelp(); + } + + function moveTagDialog(e) { + e.preventDefault(); + var sets = [{key: '0', value: '{/literal}{ts escape='js'}Main Tag Tree{/ts}{literal}'}]; + _.each(tagSets, function(tagSet) { + sets.push({key: tagSet.id, value: tagSet.name}); + }); + CRM.confirm({ + title: '{/literal}{ts escape='js'}Move to Tagset{/ts}{literal}', + message: '<label for="select-tagset">{/literal}{ts escape='js'}Select Tagset{/ts}{literal}: ' + + '<select id="select-tagset" class="crm-select2 big">' + + CRM.utils.renderOptions(sets, tagset) + + '</select>' }) - .on('dialogclose', function() { - $('input[name=select_merge_tag]', this).select2('destroy'); + .on('crmConfirm:yes', function() { + var chosen = parseInt($('#select-tagset').val()); + if (parseInt(tagset) !== chosen) { + var apiCalls = []; + _.each(selected, function(id) { + apiCalls.push(['Tag', 'create', {id: id, parent_id: chosen || ''}]); + }); + $('#mainTabContainer').block(); + CRM.api3(apiCalls, true) + .done(function() { + $('.tag-tree', $panel).jstree(true).refresh(); + $('#mainTabContainer').unblock(); + var $otherPanel = $(chosen ? '#tagset-' + chosen : '#tree'); + if ($('.tag-tree', $otherPanel).length) { + $('.tag-tree', $otherPanel).jstree(true).refresh(); + } + }); + } + }); + } + + $panel + .append('<div class="tag-tree-wrapper"><div class="tag-tree"></div><div class="tag-info"></div></div>') + .on('change', 'input[type=color]', changeColor) + .on('change', 'input[name=used_for]', changeUsedFor) + .on('click', '.clear-tag-selection', clearSelection) + .on('click', '.move-tag-button', moveTagDialog) + .on('click', '.used-for-toggle', function() { + $(this).attr('style', 'display: none !important;').next().show(); }) - .on('crmConfirm:yes', function() { - var toId = $("input[name=select_merge_tag]", this).val(); - if (!toId) { - $("input[name=select_merge_tag]", this).crmError('{/literal}{ts escape='js'}Select a tag{/ts}{literal}'); - return false; + .on('crmPopupFormSuccess crmFormSuccess', function(e, cts, data) { + if ($(e.target).hasClass('tagset-action-delete')) { + deleteTagset(); + } else if ($(e.target).hasClass('tagset-action-update')) { + updateTagset(data.tag); + } else { + $('.tag-tree', $panel).jstree(true).refresh(); } - var postUrl = {/literal}"{crmURL p='civicrm/ajax/mergeTags' h=0 }"{literal}; - var data = {fromId: tag.id, toId: toId, key:{/literal}"{crmKey name='civicrm/ajax/mergeTags'}"{literal}}; - $.ajax({ - type: "POST", - url: postUrl, - data: data, - dataType: "json", - success: function(values) { - if ( values.status == true ) { - $('#tag-' + toId).children('td.crm-tag-used_for').text(values.tagB_used_for); - $('#tag-' + tag.id).html('<td colspan="8"><div class="status message"><div class="icon inform-icon"></div>' + values.message + '</div></td>'); + }); + + plugins = ['wholerow', 'changed']; + if (!tagset) { + // Allow drag-n-drop nesting of the tag tree + plugins.push('dnd'); + } + + $('.tag-tree', $panel) + .on('changed.jstree loaded.jstree', changeSelection) + .on('move_node.jstree', moveTag) + .jstree({ + core: { + data: { + url: CRM.url('civicrm/ajax/tagTree'), + data: function(node) { + return {parent_id: node.id === '#' ? tagset : node.id}; } - } - }); + }, + check_callback: true + }, + plugins: plugins, + dnd: { + copy: false + }, + themes: { + stripes: true, + dots: false + } + }); + } + + function newTagset() { + CRM.loadForm(CRM.url('civicrm/tag/edit', {action: 'add', tagset: 1})) + .on('crmFormSuccess', function(e, data) { + tagSets[data.tag.id] = data.tag; + tagSets[data.tag.id].display_name = user.display_name; + formatTagSet(tagSets[data.tag.id]); + $("#new-tagset").before('<div id="tagset-' + data.tag.id + '">'); + $("a[href='#new-tagset']").parent().before('<li class="ui-corner-all crm-tab-button"><a href="#tagset-' + data.tag.id + '">' + data.tag.name + '</a></li>'); + $('#mainTabContainer').tabs('refresh'); + $('#mainTabContainer').tabs('option', 'active', -2); }); } + + $('#mainTabContainer') + .tabs() + .on("tabsbeforeactivate", function (event, ui) { + var id = $(ui.newPanel).attr('id'); + if (id === 'new-tagset') { + event.preventDefault(); + newTagset(); + return false; + } + if ($.inArray(id, renderedTabs) < 0) { + renderedTabs.push(id); + renderTree(ui.newPanel); + } + }); + + renderTree($('#tree')); + + // Prevent the info box from scrolling offscreen + $window.on('scroll resize', function () { + var $wrapper = $('.tag-tree-wrapper:visible'), + pos = $wrapper.offset(), + $box = $('.tag-info:visible'); + if ($window.scrollTop() + menuHeight > pos.top) { + $box.css({ + position: 'fixed', + top: menuHeight, + right: parseInt($window.width() - (pos.left + $wrapper.width())), + width: parseInt($wrapper.width() * .40) + }); + } else { + $box.removeAttr('style'); + } + }); + }); - </script> - <style type="text/css"> - .crm-container tr.child-row td:first-child { - padding-left: 2em; - } - .crm-container tr.grandchild-row td:first-child { - padding-left: 3em; - } - </style> + })(CRM.$, CRM._); +</script> +<style type="text/css"> + div.tag-tree-wrapper { + position: relative; + min-height: 250px; + } + div.tag-tree { + width: 59%; + } + div.tag-info { + width: 40%; + position: absolute; + top: 5px; + right: 0; + min-height: 100px; + border: 1px solid #aaa; + border-radius: 4px; + box-shadow: 0 0 4px #e3e3e3; + padding: 1em; + box-sizing: border-box; + background: white; + } + div.tag-info .clear-tag-selection { + position: absolute; + top: 10px; + right: 12px; + color: inherit; + opacity: .5; + } + div.tag-info .clear-tag-selection:hover, + div.tag-info .clear-tag-selection:active { + opacity: 1; + } + .tag-tree-wrapper .tag-tree a.crm-tag-item { + border-radius: 3px; + margin: 2px 0; + height: 20px; + line-height: 20px; + font-size: 12px; + padding: 0 3px; + } + #tree a.crm-tag-item { + cursor: move; + } + li.is-reserved > a:after { + content: ' *'; + } + .tag-tree-wrapper ul { + margin: 0; + padding: 0; + } + div.tag-info h4 .crm-editable { + min-width: 60%; + padding: .2em; + } + div.tag-info .crm-editable-enabled { + min-width: 5em; + } + div.tag-info .crm-editable-enabled[data-field=description] { + min-width: 60%; + } + div.tag-info input[type=color] { + cursor: pointer; + } + div.tag-info .tdl { + font-weight: bold; + color: #999; + } + div.tag-info hr { + margin: .2em 0; + } + div.tag-info .crm-submit-buttons { + margin: 10px 0 0; + } +</style> {/literal} -{/if} +<script type="text/template" id="noneSelectedTpl"> + <% if (length) {ldelim} %> + <h4>{ts}None Selected{/ts}</h4> + <hr /> + <p>{ts}Select one or more tags for details.{/ts}</p> + <% {rdelim} else {ldelim} %> + <h4>{ts}Empty Tag Set{/ts}</h4> + <hr /> + <p>{ts}No tags have been created in this set.{/ts}</p> + <% {rdelim} %> + <div class="crm-submit-buttons"> + <a href="{crmURL p="civicrm/tag/edit" q="action=add&parent_id="}<%= tagset || '' %>" class="button crm-popup"> + <span><i class="crm-i fa-plus"></i> {ts}Add Tag{/ts}</span> + </a> + <% if(tagset && adminTagsets) {ldelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=update&id="}<%= tagset %>" class="button crm-popup tagset-action-update"> + <span><i class="crm-i fa-pencil"></i> {ts}Edit Set{/ts}</span> + </a> + <% {rdelim} %> + <% if(tagset && !length && adminTagsets && (!is_reserved || adminReserved)) {ldelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= tagset %>" class="button crm-popup small-popup tagset-action-delete"> + <span><i class="crm-i fa-trash"></i> {ts}Delete Set{/ts}</span> + </a> + <% {rdelim} %> + </div> +</script> + +<script type="text/template" id="oneSelectedTpl"> + <div class="crm-entity" data-entity="Tag" data-id="<%= id %>"> + <h4> + <input type="color" value="<%= data.color %>" title="{ts}Select color{/ts}"/> + <span class="crm-editable" data-field="name"><%- text %></span> + </h4> + <hr /> + <div><span class="tdl">{ts}Description:{/ts}</span> + <span class="crm-editable" data-field="description"><%- data.description %></span> + </div> + <div><span class="tdl">{ts}Selectable:{/ts}</span> + <span class="crm-editable" data-field="is_selectable" data-type="select"><% if (data.is_selectable) {ldelim} %> {ts}Yes{/ts} <% {rdelim} else {ldelim} %> {ts}No{/ts} <% {rdelim} %></span> + </div> + <div><span class="tdl">{ts}Reserved:{/ts}</span> + <span class="<% if (adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="is_reserved" data-type="select"><% if (data.is_reserved) {ldelim} %> {ts}Yes{/ts} <% {rdelim} else {ldelim} %> {ts}No{/ts} <% {rdelim} %></span> + </div> + <% if (parent === '#' && !tagset) {ldelim} %> + <div> + <span class="tdl">{ts}Used For:{/ts}</span> + {literal} + <span class="crm-editable-enabled used-for-toggle"> + <% if (!data.used_for.length) { %><i class="crm-i fa-pencil crm-editable-placeholder"></i><% } %> + <% _.forEach(data.used_for, function(key, i) { %><%- (i ? ', ' : '') + usedFor[key] %><% }) %> + </span> + <span style="display: none"> + <% _.forEach(usedFor, function(label, key) { %> + <span style="white-space: nowrap"> + <input type="checkbox" name="used_for" value="<%= key %>" id="<%= id + '_used_for_' + key %>" <% if (data.used_for.indexOf(key) > -1) { %>checked<% } %> /> + <label for="<%= id + '_used_for_' + key %>"><%- label %></label> + </span> + <% }) %> + </span> + {/literal} + </div> + <% {rdelim} %> + <div><span class="tdl">{ts}Usage Count:{/ts}</span> <%= data.usages %></div> + <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban"></i></a> + </div> + <div class="crm-submit-buttons"> + <% if(!tagset) {ldelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=add&parent_id="}<%= id %>" class="button crm-popup" title="{ts}Create new tag under this one{/ts}"> + <span><i class="crm-i fa-plus"></i> {ts}Add Child{/ts}</span> + </a> + <% {rdelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=add&clone_from="}<%= id %>" class="button crm-popup" title="{ts}Duplicate ths tag{/ts}"> + <span><i class="crm-i fa-copy"></i> {ts}Clone Tag{/ts}</span> + </a> + <% if(!data.is_reserved || adminReserved) {ldelim} %> + <% if(tagsetCount) {ldelim} %> + <a href="#move" class="button move-tag-button" title="{ts}Move to a different tagset{/ts}"> + <span><i class="crm-i fa-share-square-o"></i> {ts}Move Tag{/ts}</span> + </a> + <% {rdelim} %> + <% if(!hasChildren) {ldelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= id %>" class="button crm-popup small-popup"> + <span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span> + </a> + <% {rdelim} %> + <% {rdelim} %> + </div> +</script> + +<script type="text/template" id="moreSelectedTpl"> + <h4>{ts 1="<%= items.length %>"}%1 Tags Selected{/ts}</h4> + <hr /> + <% if (reserved) {ldelim} %> + <p>* {ts 1="<%= reserved %>"}%1 reserved.{/ts}</p> + <% {rdelim} %> + <p><span class="tdl">{ts}Total Usage:{/ts}</span> <%= usages %></p> + <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban"></i></a> + <div class="crm-submit-buttons"> + <% if(!reserved || adminReserved) {ldelim} %> + <a href="{crmURL p="civicrm/tag/merge" q="id="}<%= items.join() %>" class="button crm-popup small-popup" title="{ts}Combine tags into one{/ts}"> + <span><i class="crm-i fa-compress"></i> {ts}Merge Tags{/ts}</span> + </a> + <% if(tagsetCount) {ldelim} %> + <a href="#move" class="button move-tag-button" title="{ts}Move to a different tagset{/ts}"> + <span><i class="crm-i fa-share-square-o"></i> {ts}Move Tags{/ts}</span> + </a> + <% {rdelim} %> + <% if(!hasChildren) {ldelim} %> + <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= items.join() %>" class="button crm-popup small-popup"> + <span><i class="crm-i fa-trash"></i> {ts}Delete All{/ts}</span> + </a> + <% {rdelim} %> + <% {rdelim} %> + </div> +</script> + +<script type="text/template" id="tagsetHelpTpl"> + <div class="help"> + <% if(is_reserved == 1) {ldelim} %><strong>{ts}Reserved{/ts}</strong><% {rdelim} %> + <% if(undefined === display_name) {ldelim} var display_name = null; {rdelim} %> + {ts 1="<%= used_for_label.join(', ') %>" 2="<%= date %>" 3="<%= display_name %>"}Tag Set for %1 (created %2 by %3).{/ts} + <% if(typeof description === 'string' && description.length) {ldelim} %><p><em><%- description %></em></p><% {rdelim} %> + </div> +</script> diff --git a/civicrm/templates/CRM/UF/Form/Block.tpl b/civicrm/templates/CRM/UF/Form/Block.tpl index ffdd708d35057253f4382659b239ee2f455f138a..da77dda5d11cfcbe248b8eea381c080d1aa83ced 100644 --- a/civicrm/templates/CRM/UF/Form/Block.tpl +++ b/civicrm/templates/CRM/UF/Form/Block.tpl @@ -29,148 +29,7 @@ {if $help_pre && $action neq 4}<div class="messages help">{$help_pre}</div>{/if} {assign var=zeroField value="Initial Non Existent Fieldset"} {assign var=fieldset value=$zeroField} - {foreach from=$fields item=field key=fieldName} - {if $field.skipDisplay} - {continue} - {/if} - {if $field.groupTitle != $fieldset} - {if $fieldset != $zeroField} - {if $groupHelpPost && $action neq 4} - <div class="messages help">{$groupHelpPost}</div> - {/if} - {if $mode ne 8} - </fieldset> - {/if} - {/if} - - {if $mode ne 8 && $action ne 1028 && $action ne 4 && !$hideFieldset} - <fieldset class="crm-profile crm-profile-id-{$field.group_id} crm-profile-name-{$field.groupName}"><legend>{$field.groupTitle}</legend> - {/if} - - {if ($form.formName eq 'Confirm' OR $form.formName eq 'ThankYou') AND $prefix neq 'honor'} - <div class="header-dark">{$field.groupTitle} </div> - {/if} - {assign var=fieldset value=`$field.groupTitle`} - {assign var=groupHelpPost value=`$field.groupHelpPost`} - {if $field.groupHelpPre && $action neq 4 && $action neq 1028} - <div class="messages help">{$field.groupHelpPre}</div> - {/if} - {/if} - - {assign var=n value=$field.name} - - {if $field.field_type eq "Formatting"} - {if $action neq 4 && $action neq 1028} - {$field.help_pre} - {/if} - {elseif $n} - {* Show explanatory text for field if not in 'view' or 'preview' modes *} - {if $field.help_pre && $action neq 4 && $action neq 1028} - <div class="crm-section helprow-{$n}-section helprow-pre" id="helprow-{$n}"> - <div class="content description">{$field.help_pre}</div> - </div> - {/if} - {if $field.options_per_line != 0} - <div class="crm-section editrow_{$n}-section form-item" id="editrow-{$n}"> - <div class="label option-label">{if $prefix}{$form.$prefix.$n.label}{else}{$form.$n.label}{/if}</div> - <div class="content 3"> - {assign var="count" value="1"} - {strip} - <table class="form-layout-compressed"> - <tr> - {* sort by fails for option per line. Added a variable to iterate through the element array*} - {assign var="index" value="1"} - {if $prefix} - {assign var="formElement" value=$form.$prefix.$n} - {else} - {assign var="formElement" value=$form.$n} - {/if} - {foreach name=outer key=key item=item from=$formElement} - {if $index < 10} - {assign var="index" value=`$index+1`} - {else} - <td class="labels font-light">{$formElement.$key.html}</td> - {if $count == $field.options_per_line} - </tr> - <tr> - {assign var="count" value="1"} - {else} - {assign var="count" value=`$count+1`} - {/if} - {/if} - {/foreach} - </tr> - </table> - {/strip} - </div> - <div class="clear"></div> - </div> - {else} - <div class="crm-section editrow_{$n}-section form-item" id="editrow-{$n}"> - <div class="label"> - {if $prefix}{$form.$prefix.$n.label}{else}{$form.$n.label}{/if} - </div> - <div class="content"> - {if $n|substr:0:3 eq 'im-'} - {assign var="provider" value=$n|cat:"-provider_id"} - {$form.$provider.html} - {/if} - - {if $n eq 'email_greeting' or $n eq 'postal_greeting' or $n eq 'addressee'} - {include file="CRM/Profile/Form/GreetingType.tpl"} - {elseif ($n eq 'group' && $form.group) || ($n eq 'tag' && $form.tag)} - {include file="CRM/Contact/Form/Edit/TagsAndGroups.tpl" type=$n title=null context="profile"} - {elseif ( $n|substr:-5:5 eq '_date' ) AND - ( $form.formName neq 'Confirm' ) AND - ( $form.formName neq 'ThankYou' ) } - {include file="CRM/common/jcalendar.tpl" elementName=$n} - {elseif ( $n|substr:-5:5 eq '_date' ) } - {assign var="date_value" value=$form.$n.value} - <span class="crm-frozen-field"> - {$date_value|date_format:"%Y-%m-%d"|crmDate:$config->dateformatshortdate} - <input type="hidden" name="{$form.$n.name}" value="{$form.$n.value}" id="{$form.$n.name}"> - </span> - {elseif $n|substr:0:5 eq 'phone'} - {assign var="phone_ext_field" value=$n|replace:'phone':'phone_ext'} - {if $prefix}{$form.$prefix.$n.html}{else}{$form.$n.html}{/if} - {if $form.$phone_ext_field.html} - {$form.$phone_ext_field.html} - {/if} - {else} - {if $prefix} - {if $n eq 'organization_name' && !empty($form.onbehalfof_id)} - {$form.onbehalfof_id.html} - {/if} - {if $field.html_type eq 'File' && $viewOnlyPrefixFileValues} - {$viewOnlyPrefixFileValues.$prefix.$n} - {else} - {$form.$prefix.$n.html} - {/if} - {elseif $field.html_type eq 'File' && $viewOnlyFileValues} - {$viewOnlyFileValues.$n} - {else} - {$form.$n.html} - {/if} - {/if} - - {*CRM-4564*} - {if $field.html_type eq 'Autocomplete-Select'} - {if $field.data_type eq 'ContactReference'} - {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $n} - {/if} - {/if} - </div> - <div class="clear"></div> - </div> - {/if} - {* Show explanatory text for field if not in 'view' or 'preview' modes *} - {if $field.help_post && $action neq 4 && $action neq 1028} - <div class="crm-section helprow-{$n}-section helprow-post" id="helprow-{$n}"> - <div class="content description">{$field.help_post}</div> - </div> - {/if} - {/if} - {/foreach} + {include file="CRM/UF/Form/Fields.tpl"} {if $field.groupHelpPost && $action neq 4 && $action neq 1028} <div class="messages help">{$field.groupHelpPost}</div> diff --git a/civicrm/templates/CRM/UF/Form/Fields.tpl b/civicrm/templates/CRM/UF/Form/Fields.tpl new file mode 100644 index 0000000000000000000000000000000000000000..4fbe9a4e7e4c33c6aecf58c78f865960a4dcdb45 --- /dev/null +++ b/civicrm/templates/CRM/UF/Form/Fields.tpl @@ -0,0 +1,143 @@ +{foreach from=$fields item=field key=fieldName} + {if $field.skipDisplay} + {continue} + {/if} + {if $field.groupTitle != $fieldset} + {if $fieldset != $zeroField} + {if $groupHelpPost && $action neq 4} + <div class="messages help">{$groupHelpPost}</div> + {/if} + {if $mode ne 8} + </fieldset> + {/if} + {/if} + + {if $mode ne 8 && $action ne 1028 && $action ne 4 && !$hideFieldset} + <fieldset class="crm-profile crm-profile-id-{$field.group_id} crm-profile-name-{$field.groupName}"><legend>{$field.groupTitle}</legend> + {/if} + + {if ($form.formName eq 'Confirm' OR $form.formName eq 'ThankYou') AND $prefix neq 'honor'} + <div class="header-dark">{$field.groupTitle} </div> + {/if} + {assign var=fieldset value=`$field.groupTitle`} + {assign var=groupHelpPost value=`$field.groupHelpPost`} + {if $field.groupHelpPre && $action neq 4 && $action neq 1028} + <div class="messages help">{$field.groupHelpPre}</div> + {/if} + {/if} + + {assign var=profileFieldName value=$field.name} + + {if $field.field_type eq "Formatting"} + {if $action neq 4 && $action neq 1028} + {$field.help_pre} + {/if} + {elseif $profileFieldName} + {* Show explanatory text for field if not in 'view' or 'preview' modes *} + {if $field.help_pre && $action neq 4 && $action neq 1028} + <div class="crm-section helprow-{$profileFieldName}-section helprow-pre" id="helprow-{$profileFieldName}"> + <div class="content description">{$field.help_pre}</div> + </div> + {/if} + {if $field.options_per_line != 0} + <div class="crm-section editrow_{$profileFieldName}-section form-item" id="editrow-{$profileFieldName}"> + <div class="label option-label">{if $prefix}{$form.$prefix.$profileFieldName.label}{else}{$form.$profileFieldName.label}{/if}</div> + <div class="content 3"> + {assign var="count" value="1"} + {strip} + <table class="form-layout-compressed"> + <tr> + {* sort by fails for option per line. Added a variable to iterate through the element array*} + {assign var="index" value="1"} + {if $prefix} + {assign var="formElement" value=$form.$prefix.$profileFieldName} + {else} + {assign var="formElement" value=$form.$profileFieldName} + {/if} + {foreach name=outer key=key item=item from=$formElement} + {if $index < 10} + {assign var="index" value=`$index+1`} + {else} + <td class="labels font-light">{$formElement.$key.html}</td> + {if $count == $field.options_per_line} + </tr> + <tr> + {assign var="count" value="1"} + {else} + {assign var="count" value=`$count+1`} + {/if} + {/if} + {/foreach} + </tr> + </table> + {/strip} + </div> + <div class="clear"></div> + </div> + {else} + <div class="crm-section editrow_{$profileFieldName}-section form-item" id="editrow-{$profileFieldName}"> + <div class="label"> + {if $prefix}{$form.$prefix.$profileFieldName.label}{else}{$form.$profileFieldName.label}{/if} + </div> + <div class="content"> + {if $profileFieldName|substr:0:3 eq 'im-'} + {assign var="provider" value=profileFieldNamen|cat:"-provider_id"} + {$form.$provider.html} + {/if} + + {if $profileFieldName eq 'email_greeting' or $profileFieldName eq 'postal_greeting' or $profileFieldName eq 'addressee'} + {include file="CRM/Profile/Form/GreetingType.tpl"} + {elseif ($profileFieldName eq 'group' && $form.group) || ($profileFieldName eq 'tag' && $form.tag)} + {include file="CRM/Contact/Form/Edit/TagsAndGroups.tpl" type=$profileFieldName title=null context="profile"} + {elseif $field.is_datetime_field && $action & 4} + {assign var="date_value" value=$form.$profileFieldName.value} + <span class="crm-frozen-field"> + {$date_value|date_format:"%Y-%m-%d"|crmDate:$config->dateformatshortdate} + <input type="hidden" + name="{$form.$profileFieldName.name}" + value="{$form.$profileFieldName.value}" id="{$form.$profileFieldName.name}" + > + </span> + {elseif $field.is_legacy_date} + {include file="CRM/common/jcalendar.tpl" elementName=$profileFieldName} + {elseif $profileFieldName|substr:0:5 eq 'phone'} + {assign var="phone_ext_field" value=$profileFieldName|replace:'phone':'phone_ext'} + {if $prefix}{$form.$prefix.$profileFieldName.html}{else}{$form.$profileFieldName.html}{/if} + {if $form.$phone_ext_field.html} + {$form.$phone_ext_field.html} + {/if} + {else} + {if $prefix} + {if $profileFieldName eq 'organization_name' && !empty($form.onbehalfof_id)} + {$form.onbehalfof_id.html} + {/if} + {if $field.html_type eq 'File' && $viewOnlyPrefixFileValues} + {$viewOnlyPrefixFileValues.$prefix.$profileFieldName} + {else} + {$form.$prefix.$profileFieldName.html} + {/if} + {elseif $field.html_type eq 'File' && $viewOnlyFileValues} + {$viewOnlyFileValues.$profileFieldName} + {else} + {$form.$profileFieldName.html} + {/if} + {/if} + + {*CRM-4564*} + {if $field.html_type eq 'Autocomplete-Select'} + {if $field.data_type eq 'ContactReference'} + {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $profileFieldName} + {/if} + {/if} + </div> + <div class="clear"></div> + </div> + {/if} + {* Show explanatory text for field if not in 'view' or 'preview' modes *} + {if $field.help_post && $action neq 4 && $action neq 1028} + <div class="crm-section helprow-{$profileFieldName}-section helprow-post" id="helprow-{$profileFieldName}"> + <div class="content description">{$field.help_post}</div> + </div> + {/if} + {/if} +{/foreach} diff --git a/civicrm/templates/CRM/UF/Form/Preview.tpl b/civicrm/templates/CRM/UF/Form/Preview.tpl index 6bede7d17b04d0c78bdef167e633d2e218323c8f..cc4b5cf7d9403bba3ed11d59fd846beb292a81ba 100644 --- a/civicrm/templates/CRM/UF/Form/Preview.tpl +++ b/civicrm/templates/CRM/UF/Form/Preview.tpl @@ -40,109 +40,10 @@ {if $help_pre && $action neq 4}<div class="messages help">{$help_pre}</div>{/if} {assign var=zeroField value="Initial Non Existent Fieldset"} {assign var=fieldset value=$zeroField} - {foreach from=$fields item=field key=fieldName} - {if $field.skipDisplay} - {continue} - {/if} - {if $field.groupTitle != $fieldset} - {if $fieldset != $zeroField} - </table> - {if $groupHelpPost} - <div class="messages help">{$groupHelpPost}</div> - {/if} - {if $mode ne 8} - </fieldset> - {/if} - {/if} - {if $mode ne 8} - <h3>{$field.groupTitle}</h3> - {/if} - {assign var=fieldset value=`$field.groupTitle`} - {assign var=groupHelpPost value=`$field.groupHelpPost`} - {if $field.groupHelpPre} - <div class="messages help">{$field.groupHelpPre}</div> - {/if} - <table class="form-layout-compressed" id="table-1"> - {/if} - {* Show explanatory text for field if not in 'view' mode *} - {if $field.help_pre && $action neq 4 && $field.field_type neq "Formatting"} - <tr><td> </td><td class="description">{$field.help_pre}</td></tr> - {/if} - {assign var=n value=$field.name} - {if $field.field_type eq "Formatting"} - <tr><td colspan="2">{$field.help_pre}</td></tr> - {elseif $field.options_per_line } - <tr> - <td class="option-label">{$form.$n.label}</td> - <td> - {assign var="count" value="1"} - {strip} - <table class="form-layout-compressed"> - <tr> - {* sort by fails for option per line. Added a variable to iterate through the element array*} - {assign var="index" value="1"} - {foreach name=outer key=key item=item from=$form.$n} - {if $index < 10} - {assign var="index" value=`$index+1`} - {else} - <td class="labels font-light">{$form.$n.$key.html}</td> - {if $count == $field.options_per_line} - </tr> - {assign var="count" value="1"} - {else} - {assign var="count" value=`$count+1`} - {/if} - {/if} - {/foreach} - </table> - {/strip} - </td> - </tr> - {else} - <tr> - <td class="label"> - {$form.$n.label} - </td> - <td> - {if $n eq 'group' && $form.group || ( $n eq 'tag' && $form.tag )} - {include file="CRM/Contact/Form/Edit/TagsAndGroups.tpl" type=$n} - {elseif $n eq 'email_greeting' or $n eq 'postal_greeting' or $n eq 'addressee'} - {include file="CRM/Profile/Form/GreetingType.tpl"} - {elseif ( $n|substr:-5:5 eq '_date' ) or ( $field.name eq 'activity_date_time' ) } - {include file="CRM/common/jcalendar.tpl" elementName=$form.$n.name} - {elseif $n|substr:0:5 eq 'phone'} - {assign var="phone_ext_field" value=$n|replace:'phone':'phone_ext'} - {$form.$n.html} - {if $form.$phone_ext_field.html} - {$form.$phone_ext_field.html} - {/if} - {else} - {if $n|substr:0:3 eq 'im-'} - {assign var="provider" value=$n|cat:"-provider_id"} - {$form.$provider.html} - {/if} - {$form.$n.html} - {if $field.is_view eq 0} - {if $field.html_type eq 'Autocomplete-Select'} - {if $field.data_type eq 'ContactReference'} - {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $n} - {/if} - {/if} - {/if} - {/if} - </td> - </tr> - {/if} - {* Show explanatory text for field if not in 'view' mode *} - {if $field.help_post && $action neq 4} - <tr><td> </td><td class="description">{$field.help_post}</td></tr> - {/if} - {/foreach} - + {include file="CRM/UF/Form/Fields.tpl"} {if $addCAPTCHA } {include file='CRM/common/ReCAPTCHA.tpl'} {/if} - </table> {if $field.groupHelpPost} <div class="messages help">{$field.groupHelpPost}</div> {/if} diff --git a/civicrm/templates/CRM/common/version.tpl b/civicrm/templates/CRM/common/version.tpl index 8df56acc47f0b8d07b1f5af746b3f2dbeadcb4b9..bf0a93eb38bf1b10361a2d8cad78c46c6a367c59 100644 --- a/civicrm/templates/CRM/common/version.tpl +++ b/civicrm/templates/CRM/common/version.tpl @@ -1 +1 @@ -4.7.16 \ No newline at end of file +4.7.17 \ No newline at end of file diff --git a/civicrm/vendor/autoload.php b/civicrm/vendor/autoload.php index 57466a25672136784330af3e27df2658ca44daa5..6d9fa7f9d95037cdb40329cdf1c61a45483fade2 100644 --- a/civicrm/vendor/autoload.php +++ b/civicrm/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5::getLoader(); +return ComposerAutoloaderInit08ca5e7ba3199d8cc11629f471bf7947::getLoader(); diff --git a/civicrm/vendor/composer/autoload_real.php b/civicrm/vendor/composer/autoload_real.php index 19e0916714e550e7b29932b5da4d07e554de9f04..ad08ffd85b5af41b09fe39512777bf9ee81ff9cb 100644 --- a/civicrm/vendor/composer/autoload_real.php +++ b/civicrm/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5 +class ComposerAutoloaderInit08ca5e7ba3199d8cc11629f471bf7947 { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit08ca5e7ba3199d8cc11629f471bf7947', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit08ca5e7ba3199d8cc11629f471bf7947', 'loadClassLoader')); $includePaths = require __DIR__ . '/include_paths.php'; array_push($includePaths, get_include_path()); @@ -46,14 +46,14 @@ class ComposerAutoloaderInitfc6c36efd254e0839a09e449fe249ca5 $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequirefc6c36efd254e0839a09e449fe249ca5($file); + composerRequire08ca5e7ba3199d8cc11629f471bf7947($file); } return $loader; } } -function composerRequirefc6c36efd254e0839a09e449fe249ca5($file) +function composerRequire08ca5e7ba3199d8cc11629f471bf7947($file) { require $file; }