ReportAutomator - Version 0.0.1

Version Notes

Schedule reports by day, week or month
Send reports in XML or CSV formats
Send reports as email attachments or save to directory via FTP
Create multiple versions of a report with different parameters
Supports multi-storefront deployments

Download this release

Release Info

Developer Graham Lubie
Extension ReportAutomator
Version 0.0.1
Comparing to
See all releases


Version 0.0.1

Files changed (52) hide show
  1. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report.php +18 -0
  2. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit.php +36 -0
  3. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Form.php +23 -0
  4. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Configuration.php +36 -0
  5. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Connection.php +119 -0
  6. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Details.php +179 -0
  7. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/History.php +66 -0
  8. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tabs.php +46 -0
  9. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Grid.php +116 -0
  10. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Abandoned.php +49 -0
  11. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Accounts.php +25 -0
  12. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Bestsellers.php +33 -0
  13. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Coupons.php +32 -0
  14. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Customer.php +23 -0
  15. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Downloads.php +46 -0
  16. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Invoiced.php +32 -0
  17. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Lowstock.php +46 -0
  18. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Orders.php +21 -0
  19. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Popular.php +48 -0
  20. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Refunded.php +32 -0
  21. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ReviewCustomer.php +23 -0
  22. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ReviewProduct.php +23 -0
  23. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Sales.php +33 -0
  24. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Search.php +26 -0
  25. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Shipping.php +32 -0
  26. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ShopProduct.php +23 -0
  27. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Sold.php +22 -0
  28. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/TagProduct.php +24 -0
  29. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Tax.php +33 -0
  30. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Totals.php +21 -0
  31. app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Viewed.php +37 -0
  32. app/code/community/Accorin/ReportAutomator/Helper/Data.php +10 -0
  33. app/code/community/Accorin/ReportAutomator/Model/Entries.php +15 -0
  34. app/code/community/Accorin/ReportAutomator/Model/Log.php +15 -0
  35. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Entries.php +15 -0
  36. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Entries/Collection.php +15 -0
  37. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Log.php +15 -0
  38. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Log/Collection.php +15 -0
  39. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Report.php +15 -0
  40. app/code/community/Accorin/ReportAutomator/Model/Mysql4/Report/Collection.php +15 -0
  41. app/code/community/Accorin/ReportAutomator/Model/Observer.php +221 -0
  42. app/code/community/Accorin/ReportAutomator/Model/Report.php +15 -0
  43. app/code/community/Accorin/ReportAutomator/controllers/Adminhtml/ReportController.php +182 -0
  44. app/code/community/Accorin/ReportAutomator/etc/adminhtml.xml +30 -0
  45. app/code/community/Accorin/ReportAutomator/etc/config.xml +114 -0
  46. app/code/community/Accorin/ReportAutomator/etc/system.xml +0 -0
  47. app/code/community/Accorin/ReportAutomator/sql/accorin_reportautomator_setup/mysql4-install-0.0.1.php +77 -0
  48. app/design/adminhtml/default/default/layout/reportautomator.xml +28 -0
  49. app/etc/modules/Accorin_ReportAutomator.xml +9 -0
  50. js/accorin/reportautomator/jquery-1.8.2.min.js +2 -0
  51. js/accorin/reportautomator/jquery.noConflict.js +1 -0
  52. js/accorin/reportautomator/jsoneditor.js +25193 -0
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_blockGroup = 'reportautomator';
12
+ $this->_controller = 'adminhtml_report';
13
+ $this->_headerText = Mage::helper('reportautomator')->__('Report Automator');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ }
17
+
18
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
8
+ {
9
+ /**
10
+ * Init class
11
+ */
12
+ public function __construct()
13
+ {
14
+ parent::__construct();
15
+ $this->_blockGroup = 'reportautomator';
16
+ $this->_controller = 'adminhtml_report';
17
+ $this->_headerText = Mage::helper('reportautomator')->__('Report Automators');
18
+ /*$this->_updateButton('delete', 'label', Mage::helper('confattr')->__('Delete Configurable Attribute'));
19
+ $this->_removeButton('save');
20
+ $this->_removeButton('reset');*/
21
+ }
22
+
23
+ /**
24
+ * Get Header text
25
+ *
26
+ * @return string
27
+ */
28
+ public function getHeaderText()
29
+ {
30
+ if (Mage::registry('entries_data') && Mage::registry('entries_data')->getId()) {
31
+ return Mage::helper('reportautomator')->__("%s - Report Automator", $this->htmlEscape(Mage::registry('entries_data')->getName()));
32
+ } else {
33
+ return Mage::helper('reportautomator')->__('Report Configuration');
34
+ }
35
+ }
36
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Form.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
8
+ {
9
+ protected function _prepareForm()
10
+ {
11
+ $form = new Varien_Data_Form(array(
12
+ 'id' => 'edit_form',
13
+ 'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
14
+ 'method' => 'post',
15
+ 'enctype' => 'multipart/form-data'
16
+ )
17
+ );
18
+
19
+ $form->setUseContainer(true);
20
+ $this->setForm($form);
21
+ return parent::_prepareForm();
22
+ }
23
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Configuration.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/6/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Tab_Configuration extends Mage_Adminhtml_Block_Widget_Form
8
+ {
9
+ protected function _prepareForm()
10
+ {
11
+ $form = new Varien_Data_Form();
12
+ $this->setForm($form);
13
+ $fieldset = $form->addFieldset('reportautomator_configuration_form', array('legend' => Mage::helper('reportautomator')->__('Report Configuration')));
14
+
15
+ $fieldset->addField('template', 'jsoneditor', array(
16
+ 'label' => Mage::helper('reportautomator')->__('Report configuration'),
17
+ 'index' => 'templatecontrol',
18
+ 'name' => 'templatecontrol',
19
+ 'style' => 'width: 600px; height:400px',
20
+ 'after_element_html' => '<small>JSON structure to handle the report configuration</small>'
21
+ ));
22
+
23
+ $fieldset->addField('template_hidden', 'hidden', array(
24
+
25
+ 'name' => 'template',
26
+ ));
27
+
28
+ if (Mage::getSingleton('adminhtml/session')->getEntriesData()) {
29
+ $form->setValues(Mage::getSingleton('adminhtml/session')->getEntriesData());
30
+ Mage::getSingleton('adminhtml/session')->setEntriesData(null);
31
+ } elseif (Mage::registry('entries_data')) {
32
+ $form->setValues(Mage::registry('entries_data')->getData());
33
+ }
34
+ return parent::_prepareForm();
35
+ }
36
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Connection.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by: Marco Segura.
5
+ * Date: 8/6/15
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Tab_Connection extends Mage_Adminhtml_Block_Widget_Form
8
+ {
9
+ protected function _prepareForm()
10
+ {
11
+
12
+ $form = new Varien_Data_Form();
13
+ $this->setForm($form);
14
+
15
+ $fieldset = $form->addFieldset('reportautomator_connection_form', array('legend' => Mage::helper('reportautomator')->__('Report connection')));
16
+
17
+ $fieldset->addField('output_id', 'select', array(
18
+ 'label' => Mage::helper('reportautomator')->__('Output type option'),
19
+ 'class' => 'required-entry',
20
+ 'required' => true,
21
+ 'name' => 'output_id',
22
+ 'after_element_html' => '<small>Select the outbound type</small>',
23
+ 'options' => array(
24
+ '0' => Mage::helper('reportautomator')->__('Email'),
25
+ '1' => Mage::helper('reportautomator')->__('FTP'),
26
+ ),
27
+ ));
28
+
29
+ $fieldset->addField('email_array', 'textarea', array(
30
+ 'label' => Mage::helper('reportautomator')->__('Collection of emails'),
31
+ 'title' => Mage::helper('reportautomator')->__('Collection of emails'),
32
+ 'name' => 'email_array',
33
+ 'class' => 'required-entry',
34
+ 'required' => true,
35
+ 'after_element_html' => '<small>Separate the emails by comma ","</small>',
36
+ ));
37
+
38
+ $fieldset->addField('ftp_host', 'text', array(
39
+ 'label' => Mage::helper('reportautomator')->__('Host'),
40
+ 'title' => Mage::helper('reportautomator')->__('Host'),
41
+ 'name' => 'ftp_host',
42
+ 'required' => true,
43
+ 'after_element_html' => '<small>FTP server host</small>',
44
+ ));
45
+
46
+ $fieldset->addField('ftp_user', 'text', array(
47
+ 'label' => Mage::helper('reportautomator')->__('Username'),
48
+ 'title' => Mage::helper('reportautomator')->__('Username'),
49
+ 'name' => 'ftp_user',
50
+ 'class' => 'required-entry',
51
+ 'required' => true,
52
+ 'after_element_html' => '<small>FTP server username</small>',
53
+ ));
54
+
55
+ $fieldset->addField('ftp_pass', 'password', array(
56
+ 'label' => Mage::helper('reportautomator')->__('Password'),
57
+ 'title' => Mage::helper('reportautomator')->__('Password'),
58
+ 'name' => 'ftp_pass',
59
+ 'class' => 'required-entry',
60
+ 'required' => true,
61
+ 'after_element_html' => '<small>FTP server password</small>',
62
+ ));
63
+
64
+ $fieldset->addField('ftp_remote_file', 'text', array(
65
+ 'label' => Mage::helper('reportautomator')->__('Remote file'),
66
+ 'title' => Mage::helper('reportautomator')->__('Remote file'),
67
+ 'class' => 'required-entry',
68
+ 'name' => 'ftp_remote_file',
69
+ 'required' => true,
70
+ 'after_element_html' => '<small>The remote file to be generated.</small>',
71
+ ));
72
+
73
+ $fieldset->addField('ftp_is_passive', 'select', array(
74
+ 'label' => Mage::helper('reportautomator')->__('Passive mode'),
75
+ 'class' => 'required-entry',
76
+ 'required' => true,
77
+ 'name' => 'ftp_is_passive',
78
+ 'options' => array(
79
+ '0' => Mage::helper('reportautomator')->__('False'),
80
+ '1' => Mage::helper('reportautomator')->__('True'),
81
+ ),
82
+ ));
83
+
84
+ if (Mage::getSingleton('adminhtml/session')->getEntriesData()) {
85
+ $form->setValues(Mage::getSingleton('adminhtml/session')->getEntriesData());
86
+ Mage::getSingleton('adminhtml/session')->setEntriesData(null);
87
+ } elseif (Mage::registry('entries_data')) {
88
+ $form->setValues(Mage::registry('entries_data')->getData());
89
+ }
90
+ return parent::_prepareForm();
91
+ }
92
+
93
+ protected function _toHtml()
94
+ {
95
+ $dependency_block = $this->getLayout()
96
+ ->createBlock('adminhtml/widget_form_element_dependence')
97
+ ->addFieldMap('output_id', 'output_id')
98
+ ->addFieldMap('email_array', 'email_array')
99
+ ->addFieldMap('ftp_host', 'ftp_host')
100
+ ->addFieldMap('ftp_user', 'ftp_user')
101
+ ->addFieldMap('ftp_pass', 'ftp_pass')
102
+ ->addFieldMap('ftp_remote_file', 'ftp_remote_file')
103
+ ->addFieldMap('ftp_is_passive', 'ftp_is_passive')
104
+ ->addFieldDependence('email_array', 'output_id', '0')
105
+ ->addFieldDependence('ftp_host', 'output_id', '1')
106
+ ->addFieldDependence('ftp_user', 'output_id', '1')
107
+ ->addFieldDependence('ftp_pass', 'output_id', '1')
108
+ ->addFieldDependence('ftp_remote_file', 'output_id', '1')
109
+ ->addFieldDependence('ftp_is_passive', 'output_id', '1')
110
+ ;
111
+
112
+ return parent::_toHtml() . $dependency_block->toHtml();
113
+ }
114
+
115
+ }
116
+
117
+
118
+
119
+
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/Details.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by: Marco Segura.
5
+ * Date: 8/6/15
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Tab_Details extends Mage_Adminhtml_Block_Widget_Form
8
+ {
9
+ protected function _prepareForm()
10
+ {
11
+
12
+ $form = new Varien_Data_Form();
13
+ $this->setForm($form);
14
+
15
+ $mainFieldset = $form->addFieldset('reportautomator_details_form', array('legend' => Mage::helper('reportautomator')->__('Report Settings')));
16
+
17
+ $mainFieldset->addField('name', 'text', array(
18
+ 'label' => Mage::helper('reportautomator')->__('Name'),
19
+ 'class' => 'required-entry',
20
+ 'required' => true,
21
+ 'name' => 'name',
22
+ 'after_element_html' => '<small>Name of the report.</small>'
23
+ ));
24
+
25
+ $mainFieldset->addField('report_id', 'hidden', array(
26
+ 'name' => 'report_id',
27
+ ));
28
+
29
+ $mainFieldset->addField('entry_id', 'hidden', array(
30
+ 'name' => 'entry_id',
31
+ ));
32
+
33
+ if (!Mage::app()->isSingleStoreMode()) {
34
+ $mainFieldset->addField('store_id', 'hidden', array(
35
+ 'name' => 'store_id',
36
+ ));
37
+ }
38
+
39
+ $mainFieldset->addField('status', 'select', array(
40
+ 'label' => Mage::helper('reportautomator')->__('Status'),
41
+ 'title' => Mage::helper('reportautomator')->__('Status'),
42
+ 'name' => 'status',
43
+ 'required' => true,
44
+ 'options' => array(
45
+ '1' => Mage::helper('reportautomator')->__('Active'),
46
+ '0' => Mage::helper('reportautomator')->__('Not active'),
47
+ ),
48
+ ));
49
+
50
+ $mainFieldset->addField('file_type', 'select', array(
51
+ 'label' => Mage::helper('reportautomator')->__('Export to:'),
52
+ 'title' => Mage::helper('reportautomator')->__('Export to:'),
53
+ 'name' => 'file_type',
54
+ 'required' => true,
55
+ 'options' => array(
56
+ '0' => Mage::helper('reportautomator')->__('CSV'),
57
+ '1' => Mage::helper('reportautomator')->__('Excel XML'),
58
+ ),
59
+ ));
60
+
61
+ if (!Mage::app()->isSingleStoreMode()) {
62
+ $mainFieldset->addField('store_name', 'label', array(
63
+ 'label' => Mage::helper('reportautomator')->__('Store Name'),
64
+ 'class' => 'required-entry',
65
+ 'required' => true,
66
+ 'name' => 'store_name',
67
+ ));
68
+ }
69
+
70
+ $fieldset = $form->addFieldset('reportautomator_schedule_form', array('legend' => Mage::helper('reportautomator')->__('Schedule Settings')));
71
+
72
+ $fieldset->addField('schedule_frequency', 'select', array(
73
+ 'label' => Mage::helper('reportautomator')->__('Cron Schedule - Frequency'),
74
+ 'title' => Mage::helper('reportautomator')->__('Cron Schedule - Frequency'),
75
+ 'required' => false,
76
+ 'name' => 'schedule_frequency',
77
+ 'options' => array(
78
+ '0' => Mage::helper('reportautomator')->__('Daily'),
79
+ '1' => Mage::helper('reportautomator')->__('Weekly'),
80
+ '2' => Mage::helper('reportautomator')->__('Monthly'),
81
+ ),
82
+ 'after_element_html' => '<small>Frequency of the report.</small>',
83
+ ));
84
+
85
+ $fieldset->addField('schedule_day', 'select', array(
86
+ 'label' => Mage::helper('reportautomator')->__('Cron Schedule - Start date'),
87
+ 'title' => Mage::helper('reportautomator')->__('Cron Schedule - Start date'),
88
+ 'required' => false,
89
+ 'name' => 'schedule_day',
90
+ 'options' => array(
91
+ '1' => Mage::helper('reportautomator')->__('1'),
92
+ '2' => Mage::helper('reportautomator')->__('2'),
93
+ '3' => Mage::helper('reportautomator')->__('3'),
94
+ '4' => Mage::helper('reportautomator')->__('4'),
95
+ '5' => Mage::helper('reportautomator')->__('5'),
96
+ '6' => Mage::helper('reportautomator')->__('6'),
97
+ '7' => Mage::helper('reportautomator')->__('7'),
98
+ '8' => Mage::helper('reportautomator')->__('8'),
99
+ '9' => Mage::helper('reportautomator')->__('9'),
100
+ '10' => Mage::helper('reportautomator')->__('10'),
101
+ '11' => Mage::helper('reportautomator')->__('11'),
102
+ '12' => Mage::helper('reportautomator')->__('12'),
103
+ '13' => Mage::helper('reportautomator')->__('13'),
104
+ '14' => Mage::helper('reportautomator')->__('14'),
105
+ '15' => Mage::helper('reportautomator')->__('15'),
106
+ '16' => Mage::helper('reportautomator')->__('16'),
107
+ '17' => Mage::helper('reportautomator')->__('17'),
108
+ '18' => Mage::helper('reportautomator')->__('18'),
109
+ '19' => Mage::helper('reportautomator')->__('19'),
110
+ '20' => Mage::helper('reportautomator')->__('20'),
111
+ '21' => Mage::helper('reportautomator')->__('21'),
112
+ '22' => Mage::helper('reportautomator')->__('22'),
113
+ '23' => Mage::helper('reportautomator')->__('23'),
114
+ '24' => Mage::helper('reportautomator')->__('24'),
115
+ '25' => Mage::helper('reportautomator')->__('25'),
116
+ '26' => Mage::helper('reportautomator')->__('26'),
117
+ '27' => Mage::helper('reportautomator')->__('27'),
118
+ '28' => Mage::helper('reportautomator')->__('28'),
119
+ '29' => Mage::helper('reportautomator')->__('29'),
120
+ '30' => Mage::helper('reportautomator')->__('30'),
121
+ ),
122
+ ));
123
+
124
+ $fieldset->addField('schedule_day_week', 'select', array(
125
+ 'label' => Mage::helper('reportautomator')->__('Cron Schedule - Week Day'),
126
+ 'title' => Mage::helper('reportautomator')->__('Cron Schedule - Week Day'),
127
+ 'required' => false,
128
+ 'name' => 'schedule_day',
129
+ 'options' => array(
130
+ '0' => Mage::helper('reportautomator')->__('Sunday'),
131
+ '1' => Mage::helper('reportautomator')->__('Monday'),
132
+ '2' => Mage::helper('reportautomator')->__('Tuesday'),
133
+ '3' => Mage::helper('reportautomator')->__('Wednesday'),
134
+ '4' => Mage::helper('reportautomator')->__('Thursday'),
135
+ '5' => Mage::helper('reportautomator')->__('Friday'),
136
+ '6' => Mage::helper('reportautomator')->__('Saturday'),
137
+ ),
138
+ ));
139
+
140
+ $fieldset->addField('schedule_date_flag', 'select', array(
141
+ 'label' => Mage::helper('reportautomator')->__('Active Period time'),
142
+ 'title' => Mage::helper('reportautomator')->__('Active Period time'),
143
+ 'name' => 'schedule_date_flag',
144
+ 'options' => array(
145
+ '0' => Mage::helper('reportautomator')->__('No'),
146
+ '1' => Mage::helper('reportautomator')->__('Yes'),
147
+ ),
148
+ 'after_element_html' => '<small class="schedule_date_flag" style="display:block">Set start and end date to the date the report is being run.</small>'
149
+ ));
150
+
151
+
152
+ if (Mage::getSingleton('adminhtml/session')->getEntriesData()) {
153
+ $form->setValues(Mage::getSingleton('adminhtml/session')->getEntriesData());
154
+ Mage::getSingleton('adminhtml/session')->setEntriesData(null);
155
+ } elseif (Mage::registry('entries_data')) {
156
+ $form->setValues(Mage::registry('entries_data')->getData());
157
+ }
158
+ return parent::_prepareForm();
159
+ }
160
+
161
+ protected function _toHtml()
162
+ {
163
+ $dependency_block = $this->getLayout()
164
+ ->createBlock('adminhtml/widget_form_element_dependence')
165
+ ->addFieldMap('schedule_frequency', 'schedule_frequency')
166
+ ->addFieldMap('schedule_day', 'schedule_day')
167
+ ->addFieldMap('schedule_day_week', 'schedule_day_week')
168
+ ->addFieldDependence('schedule_day', 'schedule_frequency', '2')
169
+ ->addFieldDependence('schedule_day_week', 'schedule_frequency', '1');
170
+
171
+ return parent::_toHtml() . $dependency_block->toHtml();
172
+ }
173
+
174
+
175
+ }
176
+
177
+
178
+
179
+
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tab/History.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by: Marco Segura.
5
+ * Date: 8/14/15
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Tab_History extends Mage_Adminhtml_Block_Widget_Grid
8
+ {
9
+ public function __construct()
10
+ {
11
+ parent::__construct();
12
+ $this->setId('history_grid');
13
+ $this->_blockGroup = 'reportautomator';
14
+ $this->_controller = 'adminhtml_history';
15
+ $this->setDefaultSort('last_executed', 'desc');
16
+ $this->setSaveParametersInSession(false);
17
+ $this->setUseAjax(true);
18
+ }
19
+
20
+ public function getGridUrl()
21
+ {
22
+ return $this->_getData('grid_url') ? $this->_getData('grid_url') : $this->getUrl('*/*/history', array('_current' => true));
23
+ }
24
+
25
+ protected function _prepareCollection()
26
+ {
27
+
28
+ $collection = Mage::getModel('reportautomator/log')->getCollection()
29
+ ->addFieldToFilter('entry_id', Mage::registry('entries_data')->getId());
30
+
31
+ $this->setCollection($collection);
32
+
33
+ return parent::_prepareCollection();
34
+ }
35
+
36
+ protected function _prepareColumns()
37
+ {
38
+
39
+ $this->addColumn('status_log', array(
40
+ 'header' => Mage::helper('reportautomator')->__('Status'),
41
+ 'index' => 'status_log',
42
+ 'type' => 'options',
43
+ 'options' => array(
44
+ 0 => 'Success',
45
+ 1 => "Failed"
46
+ )
47
+ ));
48
+
49
+ $this->addColumn('result', array(
50
+ 'header' => Mage::helper('reportautomator')->__('Result Message'),
51
+ 'index' => 'result',
52
+ 'type' => 'text',
53
+ ));
54
+
55
+ $this->addColumn('last_executed', array(
56
+ 'header' => Mage::helper('reportautomator')->__('Last executed'),
57
+ 'type' => 'datetime',
58
+ 'index' => 'last_executed',
59
+ 'width' => '150px',
60
+ ));
61
+
62
+ return parent::_prepareColumns();
63
+ }
64
+
65
+
66
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Edit/Tabs.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/6/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setId('report_tabs');
14
+ $this->setDestElementId('edit_form');
15
+ $this->setTitle(Mage::helper('reportautomator')->__('Report Configuration'));
16
+ }
17
+
18
+ protected function _beforeToHtml()
19
+ {
20
+ $this->addTab('form_details_tab', array(
21
+ 'label' => Mage::helper('reportautomator')->__('Details'),
22
+ 'title' => Mage::helper('reportautomator')->__('Details'),
23
+ 'content' => $this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tab_details')->toHtml(),
24
+ ));
25
+
26
+ $this->addTab('form_connection_tab', array(
27
+ 'label' => Mage::helper('reportautomator')->__('Connection'),
28
+ 'title' => Mage::helper('reportautomator')->__('Connection'),
29
+ 'content' => $this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tab_connection')->toHtml(),
30
+ ));
31
+
32
+ $this->addTab('form_configuration_tab', array(
33
+ 'label' => Mage::helper('reportautomator')->__('Configuration'),
34
+ 'title' => Mage::helper('reportautomator')->__('Configuration'),
35
+ 'content' => $this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tab_configuration')->toHtml(),
36
+ ));
37
+
38
+ $this->addTab('form_history_log', array(
39
+ 'label' => Mage::helper('reportautomator')->__('History Logs'),
40
+ 'title' => Mage::helper('reportautomator')->__('History Logs'),
41
+ 'content' => $this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tab_history')->toHtml(),
42
+ ));
43
+
44
+ return parent::_beforeToHtml();
45
+ }
46
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Report/Grid.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Report_Grid extends Mage_Adminhtml_Block_Widget_Grid
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setId('reportGrid');
14
+ $this->setDefaultSort('entry_id');
15
+ $this->setDefaultDir('ASC');
16
+ $this->setSaveParametersInSession(true);
17
+ $this->setSubReportSize(false);
18
+ }
19
+
20
+ public function getRowUrl($row)
21
+ {
22
+ return $this->getUrl('*/*/edit', array('id' => $row->getEntryId()));
23
+ }
24
+
25
+ protected function _prepareCollection()
26
+ {
27
+ $collection = Mage::getModel('reportautomator/entries')->getCollection();
28
+ $this->setCollection($collection);
29
+ return parent::_prepareCollection();
30
+ }
31
+
32
+ protected function _prepareColumns()
33
+ {
34
+ $this->addColumn('entry_id', array(
35
+ 'header' => Mage::helper('reportautomator')->__('ID'),
36
+ 'align' => 'right',
37
+ 'width' => '50px',
38
+ 'index' => 'entry_id',
39
+ ));
40
+
41
+ $this->addColumn('name', array(
42
+ 'header' => Mage::helper('reportautomator')->__('Name'),
43
+ 'align' => 'left',
44
+ 'sortable' => true,
45
+ 'type' => 'text',
46
+ 'default' => '--',
47
+ 'index' => 'name'
48
+ ));
49
+
50
+ $this->addColumn('schedule_frequency', array(
51
+ 'header' => Mage::helper('reportautomator')->__('Schedule'),
52
+ 'align' => 'left',
53
+ 'type' => 'options',
54
+ 'width' => '150px',
55
+ 'index' => 'schedule_frequency',
56
+ 'options' => array(
57
+ '0' => Mage::helper('reportautomator')->__('Daily'),
58
+ '1' => Mage::helper('reportautomator')->__('Weekly'),
59
+ '2' => Mage::helper('reportautomator')->__('Monthly'),
60
+ ),
61
+ ));
62
+
63
+ $this->addColumn('output_id', array(
64
+ 'header' => Mage::helper('reportautomator')->__('Output Type'),
65
+ 'align' => 'left',
66
+ 'type' => 'options',
67
+ 'width' => '120px',
68
+ 'index' => 'output_id',
69
+ 'options' => array(
70
+ '0' => Mage::helper('reportautomator')->__('Email'),
71
+ '1' => Mage::helper('reportautomator')->__('FTP'),
72
+ )
73
+ ));
74
+
75
+ $this->addColumn('status', array(
76
+ 'header' => Mage::helper('newsletter')->__('Status'),
77
+ 'index' => 'status',
78
+ 'type' => 'options',
79
+ 'width' => '120px',
80
+ 'options' => array(
81
+ 0 => Mage::helper('reportautomator')->__('Not active'),
82
+ 1 => Mage::helper('reportautomator')->__('Active'),
83
+ )
84
+ ));
85
+
86
+ if (!Mage::app()->isSingleStoreMode()) {
87
+ $this->addColumn('store_id', array(
88
+ 'index' => 'store_id',
89
+ 'header' => Mage::helper('reportautomator')->__('Store View'),
90
+ 'type' => 'options',
91
+ 'width' => '120px',
92
+ 'options' => $this->getStores(),
93
+ ));
94
+ }
95
+
96
+ $this->addColumn('created', array(
97
+ 'header' => Mage::helper('reportautomator')->__('Created At'),
98
+ 'align' => 'left',
99
+ 'type' => 'date',
100
+ 'default' => '--',
101
+ 'index' => 'created',
102
+ ));
103
+
104
+
105
+ return parent::_prepareColumns();
106
+ }
107
+
108
+ protected function getStores()
109
+ {
110
+ $store_array = Mage::getModel('core/store')->getCollection()->toOptionHash();
111
+ $store_array[0] = 'All Websites';
112
+ return $store_array;
113
+ }
114
+
115
+
116
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Abandoned.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Abandoned extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_shopcart_abandoned';
13
+ $this->_headerText = Mage::helper('reports')->__('Abandoned carts');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+
17
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
18
+ $this->addButton('reportautomator_button', array(
19
+ 'label' => Mage::helper('reports')->__('Schedule this'),
20
+ 'onclick' => "scheduleThis('".$postBackUrl."','9')"
21
+ ));
22
+ }
23
+
24
+ protected function _prepareLayout()
25
+ {
26
+ $this->setChild('store_switcher',
27
+ $this->getLayout()->createBlock('adminhtml/store_switcher')
28
+ ->setUseConfirm(false)
29
+ ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null)))
30
+ ->setTemplate('report/store/switcher.phtml')
31
+ );
32
+
33
+ return parent::_prepareLayout();
34
+ }
35
+
36
+ public function getStoreSwitcherHtml()
37
+ {
38
+ if (Mage::app()->isSingleStoreMode()) {
39
+ return '';
40
+ }
41
+ return $this->getChildHtml('store_switcher');
42
+ }
43
+
44
+ public function getGridHtml()
45
+ {
46
+ return $this->getStoreSwitcherHtml() . parent::getGridHtml();
47
+ }
48
+
49
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Accounts.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Accounts extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_customer_accounts';
13
+ $this->_headerText = Mage::helper('reports')->__('New Accounts');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+
17
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
18
+ $this->addButton('reportautomator_button', array(
19
+ 'label' => Mage::helper('reports')->__('Schedule this'),
20
+ 'onclick' => "scheduleThis('".$postBackUrl."','15')"
21
+ ));
22
+ }
23
+
24
+
25
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Bestsellers.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Bestsellers extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_sales_bestsellers';
13
+ $this->_headerText = Mage::helper('sales')->__('Products Bestsellers Report');
14
+ parent::__construct();
15
+ $this->setTemplate('report/grid/container.phtml');
16
+ $this->_removeButton('add');
17
+ $this->addButton('filter_form_submit', array(
18
+ 'label' => Mage::helper('reports')->__('Show Report'),
19
+ 'onclick' => 'filterFormSubmit()'
20
+ ));
21
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
22
+ $this->addButton('reportautomator_button', array(
23
+ 'label' => Mage::helper('reports')->__('Schedule this'),
24
+ 'onclick' => "scheduleThis('".$postBackUrl."','10')"
25
+ ));
26
+ }
27
+
28
+ public function getFilterUrl()
29
+ {
30
+ $this->getRequest()->setParam('filter', null);
31
+ return $this->getUrl('*/*/bestsellers', array('_current' => true));
32
+ }
33
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Coupons.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by: Marco Segura.
5
+ * Date: 8/7/15
6
+ */
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Coupons extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_sales_coupons';
12
+ $this->_headerText = Mage::helper('reports')->__('Coupons Usage Report');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','6')"
24
+ ));
25
+ }
26
+
27
+ public function getFilterUrl()
28
+ {
29
+ $this->getRequest()->setParam('filter', null);
30
+ return $this->getUrl('*/*/coupons', array('_current' => true));
31
+ }
32
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Customer.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Customer extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_tag_customer';
13
+ $this->_headerText = Mage::helper('reports')->__('Customers Tags');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','18')"
20
+ ));
21
+ }
22
+
23
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Downloads.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Downloads extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_product_downloads';
12
+ $this->_headerText = Mage::helper('reports')->__('Downloads');
13
+ parent::__construct();
14
+ $this->_removeButton('add');
15
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
16
+ $this->addButton('reportautomator_button', array(
17
+ 'label' => Mage::helper('reports')->__('Schedule this'),
18
+ 'onclick' => "scheduleThis('".$postBackUrl."','14')"
19
+ ));
20
+
21
+ }
22
+
23
+ protected function _prepareLayout()
24
+ {
25
+ $this->setChild('store_switcher',
26
+ $this->getLayout()->createBlock('adminhtml/store_switcher')
27
+ ->setUseConfirm(false)
28
+ ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null)))
29
+ ->setTemplate('report/store/switcher.phtml')
30
+ );
31
+ return parent::_prepareLayout();
32
+ }
33
+
34
+ public function getStoreSwitcherHtml()
35
+ {
36
+ if (!Mage::app()->isSingleStoreMode()) {
37
+ return $this->getChildHtml('store_switcher');
38
+ }
39
+ return '';
40
+ }
41
+
42
+ public function getGridHtml()
43
+ {
44
+ return $this->getStoreSwitcherHtml() . parent::getGridHtml();
45
+ }
46
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Invoiced.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Invoiced extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_sales_invoiced';
12
+ $this->_headerText = Mage::helper('reports')->__('Total Invoiced vs. Paid Report');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','3')"
24
+ ));
25
+ }
26
+
27
+ public function getFilterUrl()
28
+ {
29
+ $this->getRequest()->setParam('filter', null);
30
+ return $this->getUrl('*/*/invoiced', array('_current' => true));
31
+ }
32
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Lowstock.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Lowstock extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_product_lowstock';
12
+ $this->_headerText = Mage::helper('reports')->__('Low stock');
13
+ parent::__construct();
14
+ $this->_removeButton('add');
15
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
16
+ $this->addButton('reportautomator_button', array(
17
+ 'label' => Mage::helper('reports')->__('Schedule this'),
18
+ 'onclick' => "scheduleThis('".$postBackUrl."','13')"
19
+ ));
20
+ }
21
+
22
+ protected function _prepareLayout()
23
+ {
24
+ $this->setChild('store_switcher',
25
+ $this->getLayout()->createBlock('adminhtml/store_switcher')
26
+ ->setUseConfirm(false)
27
+ ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null)))
28
+ ->setTemplate('report/store/switcher.phtml')
29
+ );
30
+
31
+ return parent::_prepareLayout();
32
+ }
33
+
34
+ public function getStoreSwitcherHtml()
35
+ {
36
+ if (Mage::app()->isSingleStoreMode()) {
37
+ return '';
38
+ }
39
+ return $this->getChildHtml('store_switcher');
40
+ }
41
+
42
+ public function getGridHtml()
43
+ {
44
+ return $this->getStoreSwitcherHtml() . parent::getGridHtml();
45
+ }
46
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Orders.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Orders extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_customer_orders';
12
+ $this->_headerText = Mage::helper('reports')->__('Customers by number of orders');
13
+ parent::__construct();
14
+ $this->_removeButton('add');
15
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
16
+ $this->addButton('reportautomator_button', array(
17
+ 'label' => Mage::helper('reports')->__('Schedule this'),
18
+ 'onclick' => "scheduleThis('".$postBackUrl."','17')"
19
+ ));
20
+ }
21
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Popular.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Popular extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_tag_popular';
13
+ $this->_headerText = Mage::helper('reports')->__('Popular Tags');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','20')"
20
+ ));
21
+ }
22
+
23
+ protected function _prepareLayout()
24
+ {
25
+ $this->setChild('store_switcher',
26
+ $this->getLayout()->createBlock('adminhtml/store_switcher')
27
+ ->setUseConfirm(false)
28
+ ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null)))
29
+ ->setTemplate('report/store/switcher.phtml')
30
+ );
31
+
32
+ return parent::_prepareLayout();
33
+ }
34
+
35
+ public function getStoreSwitcherHtml()
36
+ {
37
+ if (Mage::app()->isSingleStoreMode()) {
38
+ return '';
39
+ }
40
+ return $this->getChildHtml('store_switcher');
41
+ }
42
+
43
+ public function getGridHtml()
44
+ {
45
+ return $this->getStoreSwitcherHtml() . parent::getGridHtml();
46
+ }
47
+
48
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Refunded.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Refunded extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_sales_refunded';
12
+ $this->_headerText = Mage::helper('reports')->__('Total Refunded Report');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','5')"
24
+ ));
25
+ }
26
+
27
+ public function getFilterUrl()
28
+ {
29
+ $this->getRequest()->setParam('filter', null);
30
+ return $this->getUrl('*/*/refunded', array('_current' => true));
31
+ }
32
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ReviewCustomer.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ReviewCustomer extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_review_customer';
13
+ $this->_headerText = Mage::helper('reports')->__('Customers Reviews');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','21')"
20
+ ));
21
+ }
22
+
23
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ReviewProduct.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ReviewProduct extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_review_product';
13
+ $this->_headerText = Mage::helper('reports')->__('Products Reviews');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','22')"
20
+ ));
21
+ }
22
+
23
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Sales.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Sales extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_sales_sales';
13
+ $this->_headerText = Mage::helper('reports')->__('Total Ordered Report');
14
+ parent::__construct();
15
+ $this->setTemplate('report/grid/container.phtml');
16
+ $this->_removeButton('add');
17
+ $this->addButton('filter_form_submit', array(
18
+ 'label' => Mage::helper('reports')->__('Show Report'),
19
+ 'onclick' => 'filterFormSubmit()'
20
+ ));
21
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
22
+ $this->addButton('reportautomator_button', array(
23
+ 'label' => Mage::helper('reports')->__('Schedule this'),
24
+ 'onclick' => "scheduleThis('".$postBackUrl."','1')"
25
+ ));
26
+ }
27
+
28
+ public function getFilterUrl()
29
+ {
30
+ $this->getRequest()->setParam('filter', null);
31
+ return $this->getUrl('*/*/sales', array('_current' => true));
32
+ }
33
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Search.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Search extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ /**
10
+ * Initialize Grid Container
11
+ *
12
+ */
13
+ public function __construct()
14
+ {
15
+ $this->_controller = 'report_search';
16
+ $this->_headerText = Mage::helper('reports')->__('Search Terms');
17
+ parent::__construct();
18
+
19
+ $this->_removeButton('add');
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','23')"
24
+ ));
25
+ }
26
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Shipping.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Shipping extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_sales_shipping';
12
+ $this->_headerText = Mage::helper('reports')->__('Total Shipped Report');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','4')"
24
+ ));
25
+ }
26
+
27
+ public function getFilterUrl()
28
+ {
29
+ $this->getRequest()->setParam('filter', null);
30
+ return $this->getUrl('*/*/shipping', array('_current' => true));
31
+ }
32
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/ShopProduct.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ShopProduct extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_shopcart_product';
13
+ $this->_headerText = Mage::helper('reports')->__('Products in carts');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','8')"
20
+ ));
21
+ }
22
+
23
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Sold.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Sold extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_product_sold';
13
+ $this->_headerText = Mage::helper('reports')->__('Products Ordered');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','11')"
20
+ ));
21
+ }
22
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/TagProduct.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_TagProduct extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+
10
+ public function __construct()
11
+ {
12
+ $this->_controller = 'report_tag_product';
13
+ $this->_headerText = Mage::helper('reports')->__('Products Tags');
14
+ parent::__construct();
15
+ $this->_removeButton('add');
16
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
17
+ $this->addButton('reportautomator_button', array(
18
+ 'label' => Mage::helper('reports')->__('Schedule this'),
19
+ 'onclick' => "scheduleThis('".$postBackUrl."','19')"
20
+ ));
21
+
22
+ }
23
+
24
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Tax.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Tax extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_sales_tax';
12
+ $this->_headerText = Mage::helper('reports')->__('Order Taxes Report Grouped by Tax Rate');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','2')"
24
+ ));
25
+ }
26
+
27
+ public function getFilterUrl()
28
+ {
29
+ $this->getRequest()->setParam('filter', null);
30
+ return $this->getUrl('*/*/tax', array('_current' => true));
31
+ }
32
+
33
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Totals.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Totals extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_customer_totals';
12
+ $this->_headerText = Mage::helper('reports')->__('Customers by Orders Total');
13
+ parent::__construct();
14
+ $this->_removeButton('add');
15
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
16
+ $this->addButton('reportautomator_button', array(
17
+ 'label' => Mage::helper('reports')->__('Schedule this'),
18
+ 'onclick' => "scheduleThis('".$postBackUrl."','16')"
19
+ ));
20
+ }
21
+ }
app/code/community/Accorin/ReportAutomator/Block/Adminhtml/Rewrite/Viewed.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by: Marco Segura.
4
+ * Date: 8/7/15
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Viewed extends Mage_Adminhtml_Block_Widget_Grid_Container
8
+ {
9
+ public function __construct()
10
+ {
11
+ $this->_controller = 'report_product_viewed';
12
+ $this->_headerText = Mage::helper('reports')->__('Most Viewed');
13
+ parent::__construct();
14
+ $this->setTemplate('report/grid/container.phtml');
15
+ $this->_removeButton('add');
16
+ $this->addButton('filter_form_submit', array(
17
+ 'label' => Mage::helper('reports')->__('Show Report'),
18
+ 'onclick' => 'filterFormSubmit()'
19
+ ));
20
+ $postBackUrl = $this->getUrl('reportautomator/adminhtml_report/schedule');
21
+ $this->addButton('reportautomator_button', array(
22
+ 'label' => Mage::helper('reports')->__('Schedule this'),
23
+ 'onclick' => "scheduleThis('".$postBackUrl."','12')"
24
+ ));
25
+ }
26
+
27
+ /**
28
+ * Get filter url
29
+ *
30
+ * @return string
31
+ */
32
+ public function getFilterUrl()
33
+ {
34
+ $this->getRequest()->setParam('filter', null);
35
+ return $this->getUrl('*/*/viewed', array('_current' => true));
36
+ }
37
+ }
app/code/community/Accorin/ReportAutomator/Helper/Data.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Helper_Data extends Mage_Core_Helper_Abstract
8
+ {
9
+
10
+ }
app/code/community/Accorin/ReportAutomator/Model/Entries.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Model_Entries extends Mage_Core_Model_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/entries');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Log.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Model_Log extends Mage_Core_Model_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/log');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Entries.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Entries extends Mage_Core_Model_Mysql4_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/entries', 'entry_id');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Entries/Collection.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Entries_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/entries');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Log.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Log extends Mage_Core_Model_Mysql4_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/log', 'log_id');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Log/Collection.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Log_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/log');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Report.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Report extends Mage_Core_Model_Mysql4_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/report', 'report_id');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Mysql4/Report/Collection.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+
7
+ class Accorin_ReportAutomator_Model_Mysql4_Report_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/report');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/Model/Observer.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by: Marco Segura.
5
+ * Date: 8/7/15
6
+ */
7
+ class Accorin_ReportAutomator_Model_Observer extends Mage_Core_Model_Abstract
8
+ {
9
+
10
+ protected $week = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
11
+
12
+ public function sendReport()
13
+ {
14
+
15
+ $EntryCollection = Mage::getModel('reportautomator/entries')->getCollection();
16
+
17
+ foreach ($EntryCollection as $entry) {
18
+ if ($entry->getStatus()) {
19
+ $schedule = $this->validateSchedule($entry);
20
+ if ($schedule) {
21
+ $this->sendProtocol($entry);
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ public function validateSchedule($entry)
28
+ {
29
+ switch ($entry->getScheduleFrequency()) {
30
+ case 0:
31
+ return true;
32
+ break;
33
+ case 1:
34
+ $weekDay = jddayofweek(cal_to_jd(CAL_GREGORIAN, date("m"), date("d"), date("Y")), 1);
35
+ if ($this->week[$entry->getScheduleDay()] == $weekDay)
36
+ return true;
37
+ else
38
+ return false;
39
+ break;
40
+ case 2:
41
+ if (date('j') == $entry->getScheduleDay())
42
+ return true;
43
+ else
44
+ return false;
45
+ break;
46
+ }
47
+ return false;
48
+ }
49
+
50
+ public function sendProtocol($entry)
51
+ {
52
+ $reportModel = Mage::getModel('reportautomator/report')->load($entry->getReportId());
53
+ if ($reportModel->getId()) {
54
+ $content = $this->getDownloadFile($entry, $reportModel->getBlock());
55
+ if ($entry->getOutputId() == 0) {
56
+ /*Email Protocol*/
57
+ $this->sendMail($content['value'], $entry->getEmailArray(), $reportModel->getName(), $entry->getFileType(), $entry->getId());
58
+ } else {
59
+ /*FTP Protocol*/
60
+ $this->sendFTP($entry, $content['value']);
61
+ }
62
+ unlink($content['value']);
63
+
64
+ }
65
+ return false;
66
+ }
67
+
68
+ public function getDownloadFile($entry, $block)
69
+ {
70
+ try {
71
+ $controller = Mage::getControllerInstance('Mage_Adminhtml_Controller_Action', Mage::app()->getRequest(), Mage::app()->getResponse());
72
+ $controller->getRequest()->setParam('website', $entry->getStoreId());
73
+ $controller->getRequest()->setParam('store_ids', $entry->getStoreId());
74
+ $layout = $controller->getLayout();
75
+ if ($entry->getTemplate() == '{}') {
76
+ $content = $layout->createBlock($block);
77
+ if ($entry->getFileType() == 0)
78
+ $content = $content->getCsvFile();
79
+ else
80
+ $content = $content->getExcelFile();
81
+ } else {
82
+ $content = $layout->createBlock($block);
83
+ $param = json_decode($entry->getTemplate());
84
+ $params = new Varien_Object();
85
+
86
+ if (!is_array($content)) {
87
+ $content = array($content);
88
+ }
89
+
90
+ foreach ($param as $key => $value) {
91
+ if (!empty($value)) {
92
+ if (is_array($value))
93
+ $value = array(implode(",", $value));
94
+ if ($key == 'from' || $key == 'to')
95
+ $value = date("Y-m-d", strtotime($value));
96
+ $params->setData($key, $value);
97
+ }
98
+ }
99
+
100
+ if ($entry->getScheduleDateFlag())
101
+ $params = $this->setRangeDates($entry, $params);
102
+
103
+ foreach ($content as $cont) {
104
+ if ($cont) {
105
+ $cont->setPeriodType($params->getData('period_type'));
106
+ $cont->setFilterData($params);
107
+ if ($entry->getFileType() == 0)
108
+ $content = $cont->getCsvFile();
109
+ else
110
+ $content = $cont->getExcelFile();
111
+ }
112
+ }
113
+ }
114
+
115
+ return $content;
116
+ } catch (Exception $e) {
117
+ Mage::log($e->getMessage());
118
+ }
119
+
120
+ }
121
+
122
+ public function setRangeDates($entry, $params)
123
+ {
124
+
125
+ switch ($entry->getScheduleFrequency()) {
126
+ case 0:
127
+ $params->setData('to', date('Y-m-d'));
128
+ $params->setData('from', date('Y-m-d'));
129
+ break;
130
+ case 1:
131
+ $params->setData('from', date('Y-m-d'));
132
+ $params->setData('to', date('Y-m-d', strtotime('-7 days')));
133
+ break;
134
+ case 2:
135
+ $params->setData('from', date('Y-m-d'));
136
+ $params->setData('to', date('Y-m-d', strtotime('-30 days')));
137
+ break;
138
+ }
139
+ return $params;
140
+ }
141
+
142
+ public function sendMail($file, $receipts, $subject, $fileType, $entryId)
143
+ {
144
+ $mail = new Zend_Mail('utf-8');
145
+ $receipts = explode(',', $receipts);
146
+
147
+ if (!empty($receipts)) {
148
+ $mailBody = "Report Automator - Report name: " . $subject . " - Date: " . date('Y-m-d');
149
+ $mail->setBodyHtml($mailBody)
150
+ ->setSubject("Report Automator - Report name: " . $subject . " - Date: " . date('Y-m-d'))
151
+ ->addTo($receipts)
152
+ ->setFrom(Mage::getStoreConfig('trans_email/ident_general/email'), "Report Automator");
153
+
154
+ $name = str_replace(" ", "_", $subject);
155
+ try {
156
+ $attachment = file_get_contents($file);
157
+ if ($fileType == 0)
158
+ $name = $name . ".csv";
159
+ else
160
+ $name = $name . ".xml";
161
+ $mail->createAttachment(
162
+ $attachment,
163
+ Zend_Mime::TYPE_OCTETSTREAM,
164
+ Zend_Mime::DISPOSITION_ATTACHMENT,
165
+ Zend_Mime::ENCODING_BASE64,
166
+ $name
167
+ );
168
+
169
+ $mail->send();
170
+ $this->saveLogs(0, $entryId, 'Report has been sent to email(s): ' . implode(',', $receipts));
171
+ } catch (Exception $e) {
172
+ $this->saveLogs(1, $entryId, 'Report has failed, error message: ' . $e->getMessage());
173
+ Mage::log($e, Zend_Log::NOTICE, 'reportautomator.log');
174
+ }
175
+ }
176
+ }
177
+
178
+ public function sendFTP($entry, $file)
179
+ {
180
+ if ($entry->getFtpIsPassive())
181
+ $isPassive = true;
182
+ else
183
+ $isPassive = false;
184
+
185
+ try {
186
+ $connectionId = ftp_connect($entry->getFtpHost());
187
+ $loginResult = ftp_login($connectionId, $entry->getFtpUser(), $entry->getFtpPass());
188
+ ftp_pasv($connectionId, $isPassive);
189
+
190
+ // *** Check connection
191
+ if ((!$connectionId) || (!$loginResult)) {
192
+ Mage::log('FTP connection has failed!. Attempted to connect to ' . $entry->getFtpHost() . ' for user ' . $entry->getFtpUser(), Zend_Log::NOTICE, "reportautomator.log");
193
+ return false;
194
+ } else {
195
+ // *** Upload the file
196
+ $upload = ftp_put($connectionId, $entry->getFtpRemoteFile(), $file, FTP_ASCII);
197
+ if (!$upload) {
198
+ Mage::log('FTP upload has failed!', Zend_Log::NOTICE, "reportautomator.log");
199
+ return false;
200
+ } else
201
+ $this->saveLogs(0, $entry->getId(), 'FTP upload has sent report successfully');
202
+ }
203
+ } catch (Exception $e) {
204
+ $this->saveLogs(1, $entry->getId(), 'Report has failed, error message: ' . $e->getMessage());
205
+ Mage::log($e, Zend_Log::NOTICE, 'reportautomator.log');
206
+ }
207
+ }
208
+
209
+ public function saveLogs($status, $entry_id, $result)
210
+ {
211
+
212
+ $model = Mage::getModel('reportautomator/log');
213
+ $postData = array(
214
+ 'entry_id' => $entry_id,
215
+ 'status_log' => $status,
216
+ 'result' => $result
217
+ );
218
+ $model->setData($postData);
219
+ $model->save();
220
+ }
221
+ }
app/code/community/Accorin/ReportAutomator/Model/Report.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Model_Report extends Mage_Core_Model_Abstract
8
+ {
9
+
10
+ protected function _construct()
11
+ {
12
+ $this->_init('reportautomator/report');
13
+ }
14
+
15
+ }
app/code/community/Accorin/ReportAutomator/controllers/Adminhtml/ReportController.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: marcosegura
6
+ */
7
+ class Accorin_ReportAutomator_Adminhtml_ReportController extends Mage_Adminhtml_Controller_Action
8
+ {
9
+ public function indexAction()
10
+ {
11
+ $this->_initAction();
12
+ $this->renderLayout();
13
+ //Zend_Debug::dump($this->getLayout()->getUpdate()->getHandles());
14
+ }
15
+
16
+ protected function _initAction()
17
+ {
18
+ $this->loadLayout()
19
+ ->_setActiveMenu('system/reportautomator')
20
+ ->_addBreadcrumb(Mage::helper('reportautomator')->__('Report Automators'), Mage::helper('reportautomator')->__('Report Automators'));
21
+ return $this;
22
+ }
23
+
24
+ public function gridAction()
25
+ {
26
+ $this->loadLayout();
27
+ $this->getResponse()->setBody($this->getLayout()->createBlock('accorin_reportautomator_adminhtml/report_grid')->toHtml());
28
+ $this->renderLayout();
29
+ }
30
+
31
+ public function editAction()
32
+ {
33
+ $EntryId = $this->getRequest()->getParam('id');
34
+ $ReportId = $this->getRequest()->getParam('report_id');
35
+ $template = $this->getRequest()->getParam('template');
36
+ $store_id = $this->getRequest()->getParam('website');
37
+ $entryModel = Mage::getModel('reportautomator/entries')->load($EntryId);
38
+
39
+ if ($ReportId) {
40
+ $entryCollection = Mage::getModel('reportautomator/entries')->getCollection();
41
+ foreach ($entryCollection as $entries) {
42
+ if ($ReportId == $entries->getReportId() AND $store_id == $entries->getStoreId())
43
+ $entryModel = $entries;
44
+ }
45
+
46
+ if (empty($entryModel->getData())) {
47
+ $entryModel->setData("report_id", $ReportId);
48
+ $reportModel = Mage::getModel('reportautomator/report')->load($ReportId);
49
+ $entryModel->setData("name", $reportModel->getName());
50
+ if ($template)
51
+ $entryModel->setData("template", $template);
52
+ }
53
+ }
54
+
55
+ if ($entryModel->getId() || $EntryId == 0) {
56
+ $entryModel->setData('schedule_day_week', $entryModel->getData('schedule_day'));
57
+ if ($store_id) {
58
+ $nameStore = Mage::getModel('core/store')->load($store_id)->getName();
59
+ $entryModel->setData('store_id', $store_id);
60
+ } else
61
+ $nameStore = Mage::getModel('core/store')->load($entryModel->getData('store_id'))->getName();
62
+
63
+ if (!$nameStore)
64
+ $nameStore = "All Websites";
65
+
66
+ $entryModel->setData('store_name', $nameStore);
67
+
68
+ Mage::register('entries_data', $entryModel);
69
+
70
+ $this->loadLayout();
71
+ $this->_setActiveMenu('system/reportautomator');
72
+
73
+ $this->_addBreadcrumb(Mage::helper('reportautomator')->__('Report Automators'), Mage::helper('reportautomator')->__('Report Automators'));
74
+ $this->_addBreadcrumb(Mage::helper('reportautomator')->__('Report Automators'), Mage::helper('reportautomator')->__('Report Automators'));
75
+
76
+ $this->getLayout()->getBlock('head')->setCanLoadExtJs(true);
77
+
78
+ $this->_addContent($this->getLayout()->createBlock('reportautomator/adminhtml_report_edit'))
79
+ ->_addLeft($this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tabs'));
80
+
81
+ $this->renderLayout();
82
+ } else {
83
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('reportautomator')->__('Report entry does not exist'));
84
+ $this->_redirect('*/*/');
85
+ }
86
+ }
87
+
88
+ public function scheduleAction()
89
+ {
90
+ $this->_forward('edit');
91
+ }
92
+
93
+ public function newAction()
94
+ {
95
+ $this->_forward('edit');
96
+ }
97
+
98
+ public function historyAction()
99
+ {
100
+ $logId = $this->getRequest()->getParam('id');
101
+ $logModel = Mage::getModel('reportautomator/log')->load($logId);
102
+
103
+
104
+ Mage::register('entries_data', $logModel);
105
+
106
+ $this->getResponse()->setBody(
107
+ $this->getLayout()->createBlock('reportautomator/adminhtml_report_edit_tab_history')->toHtml()
108
+ );
109
+ }
110
+
111
+
112
+ public function deleteAction()
113
+ {
114
+ if ($this->getRequest()->getParam('id') > 0) {
115
+ try {
116
+ $EntryModel = Mage::getModel('reportautomator/entries');
117
+ $EntryModel->setId($this->getRequest()->getParam('id'))
118
+ ->delete();
119
+
120
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Report Automator was successfully deleted'));
121
+ $this->_redirect('*/*/');
122
+ } catch (Exception $e) {
123
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
124
+ $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
125
+ }
126
+ }
127
+ $this->_redirect('*/*/');
128
+ }
129
+
130
+
131
+ public function saveAction()
132
+ {
133
+ if ($this->getRequest()->getPost()) {
134
+ try {
135
+ $postData = $this->getRequest()->getPost();
136
+ $entryModel = Mage::getModel('reportautomator/entries');
137
+
138
+ $id = $this->getRequest()->getParam('id');
139
+ if (empty($postData['entry_id']))
140
+ unset($postData['entry_id']);
141
+
142
+ $entryModel->setData($postData);
143
+
144
+ if ($id)
145
+ $entryModel->setEntryId($id);
146
+ try {
147
+ $entryModel->save();
148
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Report entry was successfully saved'));
149
+ Mage::getSingleton('adminhtml/session')->setEntryData(false);
150
+ } catch (Exception $ex) {
151
+ $this->_redirect('*/*/');
152
+ return;
153
+ }
154
+
155
+ } catch (Exception $e) {
156
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
157
+ Mage::getSingleton('adminhtml/session')->setFlowData($this->getRequest()->getPost());
158
+ $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
159
+ return;
160
+ }
161
+ }
162
+ $this->_redirect('*/*/');
163
+ }
164
+
165
+ protected function _sendUploadResponse($fileName, $content, $contentType = 'application/octet-stream')
166
+ {
167
+ $response = $this->getResponse();
168
+ $response->setHeader('HTTP/1.1 200 OK', '');
169
+ $response->setHeader('Pragma', 'public', true);
170
+ $response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true);
171
+ $response->setHeader('Content-Disposition', 'attachment; filename=' . $fileName);
172
+ $response->setHeader('Last-Modified', date('r'));
173
+ $response->setHeader('Accept-Ranges', 'bytes');
174
+ $response->setHeader('Content-Length', strlen($content));
175
+ $response->setHeader('Content-type', $contentType);
176
+ $response->setBody($content);
177
+ $response->sendResponse();
178
+ die;
179
+ }
180
+
181
+
182
+ }
app/code/community/Accorin/ReportAutomator/etc/adminhtml.xml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <menu>
4
+ <system>
5
+ <children>
6
+ <reportautomator translate="title">
7
+ <title>Report Automator</title>
8
+ <sort_order>0</sort_order>
9
+ <action>reportautomator/adminhtml_report</action>
10
+ </reportautomator>
11
+ </children>
12
+ </system>
13
+ </menu>
14
+ <acl>
15
+ <resources>
16
+ <admin>
17
+ <children>
18
+ <system>
19
+ <children>
20
+ <reportautomator translate="title">
21
+ <title>Report Automators</title>
22
+ <sort_order>0</sort_order>
23
+ </reportautomator>
24
+ </children>
25
+ </system>
26
+ </children>
27
+ </admin>
28
+ </resources>
29
+ </acl>
30
+ </config>
app/code/community/Accorin/ReportAutomator/etc/config.xml ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Accorin_ReportAutomator>
5
+ <version>0.0.1</version>
6
+ </Accorin_ReportAutomator>
7
+ </modules>
8
+ <global>
9
+ <blocks>
10
+ <reportautomator>
11
+ <class>Accorin_ReportAutomator_Block</class>
12
+ </reportautomator>
13
+ <adminhtml>
14
+ <rewrite>
15
+ <report_sales_sales>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Sales</report_sales_sales>
16
+ <report_sales_tax>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Tax</report_sales_tax>
17
+ <report_sales_invoiced>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Invoiced</report_sales_invoiced>
18
+ <report_sales_shipping>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Shipping</report_sales_shipping>
19
+ <report_sales_refunded>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Refunded</report_sales_refunded>
20
+ <report_sales_coupons>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Coupons</report_sales_coupons>
21
+ <report_shopcart_product>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ShopProduct</report_shopcart_product>
22
+ <report_shopcart_abandoned>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Abandoned</report_shopcart_abandoned>
23
+ <report_sales_bestsellers>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Bestsellers</report_sales_bestsellers>
24
+ <report_product_sold>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Sold</report_product_sold>
25
+ <report_product_viewed>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Viewed</report_product_viewed>
26
+ <report_product_lowstock>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Lowstock</report_product_lowstock>
27
+ <report_product_downloads>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Downloads</report_product_downloads>
28
+ <report_customer_accounts>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Accounts</report_customer_accounts>
29
+ <report_customer_totals>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Totals</report_customer_totals>
30
+ <report_customer_orders>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Orders</report_customer_orders>
31
+ <report_tag_customer>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Customer</report_tag_customer>
32
+ <report_tag_product>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_TagProduct</report_tag_product>
33
+ <report_tag_popular>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Popular</report_tag_popular>
34
+ <report_review_customer>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ReviewCustomer</report_review_customer>
35
+ <report_review_product>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_ReviewProduct</report_review_product>
36
+ <report_search>Accorin_ReportAutomator_Block_Adminhtml_Rewrite_Search</report_search>
37
+ </rewrite>
38
+ </adminhtml>
39
+ </blocks>
40
+ <models>
41
+ <reportautomator>
42
+ <class>Accorin_ReportAutomator_Model</class>
43
+ <resourceModel>reportautomator_mysql4</resourceModel>
44
+ </reportautomator>
45
+ <reportautomator_mysql4>
46
+ <class>Accorin_ReportAutomator_Model_Mysql4</class>
47
+ <entities>
48
+ <entries>
49
+ <table>reportautomator_entries</table>
50
+ </entries>
51
+ <report>
52
+ <table>reportautomator_report</table>
53
+ </report>
54
+ <log>
55
+ <table>reportautomator_log</table>
56
+ </log>
57
+ </entities>
58
+ </reportautomator_mysql4>
59
+ </models>
60
+ <helpers>
61
+ <reportautomator>
62
+ <class>Accorin_ReportAutomator_Helper</class>
63
+ </reportautomator>
64
+ </helpers>
65
+ <resources>
66
+ <accorin_reportautomator_setup>
67
+ <setup>
68
+ <module>Accorin_ReportAutomator</module>
69
+ </setup>
70
+ <connection>
71
+ <use>core_setup</use>
72
+ </connection>
73
+ </accorin_reportautomator_setup>
74
+ <reportautomator_write>
75
+ <connection>
76
+ <use>core_write</use>
77
+ </connection>
78
+ </reportautomator_write>
79
+ <reportautomator_read>
80
+ <connection>
81
+ <use>core_read</use>
82
+ </connection>
83
+ </reportautomator_read>
84
+ </resources>
85
+ </global>
86
+ <adminhtml>
87
+ <layout>
88
+ <updates>
89
+ <reportautomator>
90
+ <file>reportautomator.xml</file>
91
+ </reportautomator>
92
+ </updates>
93
+ </layout>
94
+ </adminhtml>
95
+ <crontab>
96
+ <jobs>
97
+ <reportautomator_schedule>
98
+ <schedule><cron_expr>0 0 * * *</cron_expr></schedule>
99
+ <run><model>reportautomator/observer::sendReport</model></run>
100
+ </reportautomator_schedule>
101
+ </jobs>
102
+ </crontab>
103
+ <admin>
104
+ <routers>
105
+ <reportautomator>
106
+ <use>admin</use>
107
+ <args>
108
+ <module>Accorin_ReportAutomator</module>
109
+ <frontName>reportautomator</frontName>
110
+ </args>
111
+ </reportautomator>
112
+ </routers>
113
+ </admin>
114
+ </config>
app/code/community/Accorin/ReportAutomator/etc/system.xml ADDED
File without changes
app/code/community/Accorin/ReportAutomator/sql/accorin_reportautomator_setup/mysql4-install-0.0.1.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: marcosegura
5
+ */
6
+ /* @var $installer Mage_Core_Model_Resource_Setup */
7
+ $installer = $this;
8
+
9
+ $installer->startSetup();
10
+
11
+ $installer->run("
12
+ CREATE TABLE IF NOT EXISTS `reportautomator_entries` (
13
+ `entry_id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
14
+ `report_id` int(11) NOT NULL DEFAULT '0',
15
+ `name` varchar(255) NOT NULL DEFAULT '',
16
+ `status` tinyint(4) NOT NULL DEFAULT '0',
17
+ `output_id` tinyint(4) DEFAULT NULL,
18
+ `file_type` tinyint(4) NOT NULL DEFAULT '0',
19
+ `email_array` text DEFAULT '',
20
+ `ftp_user` varchar(255) DEFAULT '',
21
+ `ftp_pass` varchar(255) DEFAULT '',
22
+ `ftp_host` varchar(255) DEFAULT '',
23
+ `ftp_is_passive` tinyint(4) NOT NULL DEFAULT '0',
24
+ `ftp_remote_file` varchar(255) DEFAULT '',
25
+ `schedule_frequency` int(2) DEFAULT '0',
26
+ `schedule_day` int(2) DEFAULT '0',
27
+ `schedule_date_flag` tinyint(4) NOT NULL DEFAULT '0',
28
+ `template` text NOT NULL,
29
+ `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
30
+ `store_id` tinyint(4) NOT NULL DEFAULT '0'
31
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
32
+ ");
33
+
34
+ $installer->run("
35
+ CREATE TABLE IF NOT EXISTS `reportautomator_report` (
36
+ `report_id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
37
+ `name` varchar(255) DEFAULT NULL,
38
+ `block` text NOT NULL
39
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
40
+ ");
41
+
42
+ $installer->run("
43
+ CREATE TABLE IF NOT EXISTS `reportautomator_log` (
44
+ `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
45
+ `entry_id` int(11) unsigned NOT NULL,
46
+ `status_log` tinyint(4) NOT NULL DEFAULT '0',
47
+ `last_executed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
48
+ `result` text NOT NULL
49
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
50
+ ");
51
+
52
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (1, 'Sales Orders', 'adminhtml/report_sales_sales_grid')");
53
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (2, 'Sales Tax', 'adminhtml/report_sales_tax_grid')");
54
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (3, 'Sales Invoiced', 'adminhtml/report_sales_invoiced_grid')");
55
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (4, 'Sales Shipping', 'adminhtml/report_sales_shipping_grid')");
56
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (5, 'Sales Refunds', 'adminhtml/report_sales_refunded_grid')");
57
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (6, 'Sales Coupons', 'adminhtml/report_sales_coupons_grid')");
58
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (7, 'Sales Paypal', '')");
59
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (8, 'Shopping Cart Products', 'adminhtml/report_shopcart_product_grid')");
60
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (9, 'Shopping Cart Abandoned', 'adminhtml/report_shopcart_abandoned_grid')");
61
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (10, 'Products Bestsellers', 'adminhtml/report_sales_bestsellers_grid')");
62
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (11, 'Products Ordered', 'adminhtml/report_product_sold_grid')");
63
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (12, 'Products Most Viewed', 'adminhtml/report_product_viewed_grid')");
64
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (13, 'Products Low Stock', 'adminhtml/report_product_lowstock_grid')");
65
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (14, 'Products Downloads', 'adminhtml/report_product_downloads_grid')");
66
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (15, 'Customer New Accounts', 'adminhtml/report_customer_accounts_grid')");
67
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (16, 'Customers by Order Total', 'adminhtml/report_customer_totals_grid')");
68
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (17, 'Customers by Number of Orders', 'adminhtml/report_customer_orders_grid')");
69
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (18, 'Tag Customers', 'adminhtml/report_tag_customer_grid')");
70
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (19, 'Tag Products', 'adminhtml/report_tag_product_grid')");
71
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (20, 'Tag Popular', 'adminhtml/report_tag_popular_grid')");
72
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (21, 'Review Customers', 'adminhtml/report_review_customer_grid')");
73
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (22, 'Review Products', 'adminhtml/report_review_product_grid')");
74
+ $installer->run("INSERT INTO `reportautomator_report` VALUES (23, 'Search Terms', 'adminhtml/report_search_grid')");
75
+
76
+
77
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/reportautomator.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <reportautomator_adminhtml_report_index>
4
+ <reference name="content">
5
+ <block type="reportautomator/adminhtml_report" name="reportautomator"/>
6
+ </reference>
7
+ </reportautomator_adminhtml_report_index>
8
+
9
+ <default>
10
+ <reference name="head">
11
+ <action method="addJs">
12
+ <script>accorin/reportautomator/jquery-1.8.2.min.js</script>
13
+ </action>
14
+ <action method="addJs">
15
+ <script>accorin/reportautomator/jquery.noConflict.js</script>
16
+ </action>
17
+ <action method="addJs">
18
+ <file>accorin/reportautomator/jsoneditor.min.js</file>
19
+ </action>
20
+ <action method="addJs">
21
+ <file>accorin/reportautomator/reportautomator.js</file>
22
+ </action>
23
+ <action method="addCss">
24
+ <name>jsoneditor.css</name>
25
+ </action>
26
+ </reference>
27
+ </default>
28
+ </layout>
app/etc/modules/Accorin_ReportAutomator.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Accorin_ReportAutomator>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Accorin_ReportAutomator>
8
+ </modules>
9
+ </config>
js/accorin/reportautomator/jquery-1.8.2.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! jQuery v1.8.2 jquery.com | jquery.org/license */
2
+ (function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
js/accorin/reportautomator/jquery.noConflict.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery.noConflict();
js/accorin/reportautomator/jsoneditor.js ADDED
@@ -0,0 +1,26300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jsoneditor.js
3
+ *
4
+ * @brief
5
+ * JSONEditor is a web-based tool to view, edit, and format JSON.
6
+ * It shows data a clear, editable treeview.
7
+ *
8
+ * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+
9
+ *
10
+ * @license
11
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
12
+ * use this file except in compliance with the License. You may obtain a copy
13
+ * of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
20
+ * License for the specific language governing permissions and limitations under
21
+ * the License.
22
+ *
23
+ * Copyright (c) 2011-2015 Jos de Jong, http://jsoneditoronline.org
24
+ *
25
+ * @author Jos de Jong, <wjosdejong@gmail.com>
26
+ * @version 4.1.3
27
+ * @date 2015-03-17
28
+ */
29
+ (function webpackUniversalModuleDefinition(root, factory) {
30
+ if(typeof exports === 'object' && typeof module === 'object')
31
+ module.exports = factory();
32
+ else if(typeof define === 'function' && define.amd)
33
+ define(factory);
34
+ else if(typeof exports === 'object')
35
+ exports["JSONEditor"] = factory();
36
+ else
37
+ root["JSONEditor"] = factory();
38
+ })(this, function() {
39
+ return /******/ (function(modules) { // webpackBootstrap
40
+ /******/ // The module cache
41
+ /******/ var installedModules = {};
42
+
43
+ /******/ // The require function
44
+ /******/ function __webpack_require__(moduleId) {
45
+
46
+ /******/ // Check if module is in cache
47
+ /******/ if(installedModules[moduleId])
48
+ /******/ return installedModules[moduleId].exports;
49
+
50
+ /******/ // Create a new module (and put it into the cache)
51
+ /******/ var module = installedModules[moduleId] = {
52
+ /******/ exports: {},
53
+ /******/ id: moduleId,
54
+ /******/ loaded: false
55
+ /******/ };
56
+
57
+ /******/ // Execute the module function
58
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
59
+
60
+ /******/ // Flag the module as loaded
61
+ /******/ module.loaded = true;
62
+
63
+ /******/ // Return the exports of the module
64
+ /******/ return module.exports;
65
+ /******/ }
66
+
67
+
68
+ /******/ // expose the modules object (__webpack_modules__)
69
+ /******/ __webpack_require__.m = modules;
70
+
71
+ /******/ // expose the module cache
72
+ /******/ __webpack_require__.c = installedModules;
73
+
74
+ /******/ // __webpack_public_path__
75
+ /******/ __webpack_require__.p = "";
76
+
77
+ /******/ // Load entry module and return exports
78
+ /******/ return __webpack_require__(0);
79
+ /******/ })
80
+ /************************************************************************/
81
+ /******/ ([
82
+ /* 0 */
83
+ /***/ function(module, exports, __webpack_require__) {
84
+
85
+ var treemode = __webpack_require__(1);
86
+ var textmode = __webpack_require__(2);
87
+ var util = __webpack_require__(3);
88
+
89
+ /**
90
+ * @constructor JSONEditor
91
+ * @param {Element} container Container element
92
+ * @param {Object} [options] Object with options. available options:
93
+ * {String} mode Editor mode. Available values:
94
+ * 'tree' (default), 'view',
95
+ * 'form', 'text', and 'code'.
96
+ * {function} change Callback method, triggered
97
+ * on change of contents
98
+ * {Boolean} search Enable search box.
99
+ * True by default
100
+ * Only applicable for modes
101
+ * 'tree', 'view', and 'form'
102
+ * {Boolean} history Enable history (undo/redo).
103
+ * True by default
104
+ * Only applicable for modes
105
+ * 'tree', 'view', and 'form'
106
+ * {String} name Field name for the root node.
107
+ * Only applicable for modes
108
+ * 'tree', 'view', and 'form'
109
+ * {Number} indentation Number of indentation
110
+ * spaces. 4 by default.
111
+ * Only applicable for
112
+ * modes 'text' and 'code'
113
+ * @param {Object | undefined} json JSON object
114
+ */
115
+ function JSONEditor (container, options, json) {
116
+ if (!(this instanceof JSONEditor)) {
117
+ throw new Error('JSONEditor constructor called without "new".');
118
+ }
119
+
120
+ // check for unsupported browser (IE8 and older)
121
+ var ieVersion = util.getInternetExplorerVersion();
122
+ if (ieVersion != -1 && ieVersion < 9) {
123
+ throw new Error('Unsupported browser, IE9 or newer required. ' +
124
+ 'Please install the newest version of your browser.');
125
+ }
126
+
127
+ if (arguments.length) {
128
+ this._create(container, options, json);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Configuration for all registered modes. Example:
134
+ * {
135
+ * tree: {
136
+ * mixin: TreeEditor,
137
+ * data: 'json'
138
+ * },
139
+ * text: {
140
+ * mixin: TextEditor,
141
+ * data: 'text'
142
+ * }
143
+ * }
144
+ *
145
+ * @type { Object.<String, {mixin: Object, data: String} > }
146
+ */
147
+ JSONEditor.modes = {};
148
+
149
+ /**
150
+ * Create the JSONEditor
151
+ * @param {Element} container Container element
152
+ * @param {Object} [options] See description in constructor
153
+ * @param {Object | undefined} json JSON object
154
+ * @private
155
+ */
156
+ JSONEditor.prototype._create = function (container, options, json) {
157
+ this.container = container;
158
+ this.options = options || {};
159
+ this.json = json || {};
160
+
161
+ var mode = this.options.mode || 'tree';
162
+ this.setMode(mode);
163
+ };
164
+
165
+ /**
166
+ * Detach the editor from the DOM
167
+ * @private
168
+ */
169
+ JSONEditor.prototype._delete = function () {};
170
+
171
+ /**
172
+ * Set JSON object in editor
173
+ * @param {Object | undefined} json JSON data
174
+ */
175
+ JSONEditor.prototype.set = function (json) {
176
+ this.json = json;
177
+ };
178
+
179
+ /**
180
+ * Get JSON from the editor
181
+ * @returns {Object} json
182
+ */
183
+ JSONEditor.prototype.get = function () {
184
+ return this.json;
185
+ };
186
+
187
+ /**
188
+ * Set string containing JSON for the editor
189
+ * @param {String | undefined} jsonText
190
+ */
191
+ JSONEditor.prototype.setText = function (jsonText) {
192
+ this.json = util.parse(jsonText);
193
+ };
194
+
195
+ /**
196
+ * Get stringified JSON contents from the editor
197
+ * @returns {String} jsonText
198
+ */
199
+ JSONEditor.prototype.getText = function () {
200
+ return JSON.stringify(this.json);
201
+ };
202
+
203
+ /**
204
+ * Set a field name for the root node.
205
+ * @param {String | undefined} name
206
+ */
207
+ JSONEditor.prototype.setName = function (name) {
208
+ if (!this.options) {
209
+ this.options = {};
210
+ }
211
+ this.options.name = name;
212
+ };
213
+
214
+ /**
215
+ * Get the field name for the root node.
216
+ * @return {String | undefined} name
217
+ */
218
+ JSONEditor.prototype.getName = function () {
219
+ return this.options && this.options.name;
220
+ };
221
+
222
+ /**
223
+ * Change the mode of the editor.
224
+ * JSONEditor will be extended with all methods needed for the chosen mode.
225
+ * @param {String} mode Available modes: 'tree' (default), 'view', 'form',
226
+ * 'text', and 'code'.
227
+ */
228
+ JSONEditor.prototype.setMode = function (mode) {
229
+ var container = this.container,
230
+ options = util.extend({}, this.options),
231
+ data,
232
+ name;
233
+
234
+ options.mode = mode;
235
+ var config = JSONEditor.modes[mode];
236
+ if (config) {
237
+ try {
238
+ var asText = (config.data == 'text');
239
+ name = this.getName();
240
+ data = this[asText ? 'getText' : 'get'](); // get text or json
241
+
242
+ this._delete();
243
+ util.clear(this);
244
+ util.extend(this, config.mixin);
245
+ this.create(container, options);
246
+
247
+ this.setName(name);
248
+ this[asText ? 'setText' : 'set'](data); // set text or json
249
+
250
+ if (typeof config.load === 'function') {
251
+ try {
252
+ config.load.call(this);
253
+ }
254
+ catch (err) {}
255
+ }
256
+ }
257
+ catch (err) {
258
+ this._onError(err);
259
+ }
260
+ }
261
+ else {
262
+ throw new Error('Unknown mode "' + options.mode + '"');
263
+ }
264
+ };
265
+
266
+ /**
267
+ * Throw an error. If an error callback is configured in options.error, this
268
+ * callback will be invoked. Else, a regular error is thrown.
269
+ * @param {Error} err
270
+ * @private
271
+ */
272
+ JSONEditor.prototype._onError = function(err) {
273
+ // TODO: onError is deprecated since version 2.2.0. cleanup some day
274
+ if (typeof this.onError === 'function') {
275
+ util.log('WARNING: JSONEditor.onError is deprecated. ' +
276
+ 'Use options.error instead.');
277
+ this.onError(err);
278
+ }
279
+
280
+ if (this.options && typeof this.options.error === 'function') {
281
+ this.options.error(err);
282
+ }
283
+ else {
284
+ throw err;
285
+ }
286
+ };
287
+
288
+ /**
289
+ * Register a plugin with one ore multiple modes for the JSON Editor.
290
+ *
291
+ * A mode is described as an object with properties:
292
+ *
293
+ * - `mode: String` The name of the mode.
294
+ * - `mixin: Object` An object containing the mixin functions which
295
+ * will be added to the JSONEditor. Must contain functions
296
+ * create, get, getText, set, and setText. May have
297
+ * additional functions.
298
+ * When the JSONEditor switches to a mixin, all mixin
299
+ * functions are added to the JSONEditor, and then
300
+ * the function `create(container, options)` is executed.
301
+ * - `data: 'text' | 'json'` The type of data that will be used to load the mixin.
302
+ * - `[load: function]` An optional function called after the mixin
303
+ * has been loaded.
304
+ *
305
+ * @param {Object | Array} mode A mode object or an array with multiple mode objects.
306
+ */
307
+ JSONEditor.registerMode = function (mode) {
308
+ var i, prop;
309
+
310
+ if (util.isArray(mode)) {
311
+ // multiple modes
312
+ for (i = 0; i < mode.length; i++) {
313
+ JSONEditor.registerMode(mode[i]);
314
+ }
315
+ }
316
+ else {
317
+ // validate the new mode
318
+ if (!('mode' in mode)) throw new Error('Property "mode" missing');
319
+ if (!('mixin' in mode)) throw new Error('Property "mixin" missing');
320
+ if (!('data' in mode)) throw new Error('Property "data" missing');
321
+ var name = mode.mode;
322
+ if (name in JSONEditor.modes) {
323
+ throw new Error('Mode "' + name + '" already registered');
324
+ }
325
+
326
+ // validate the mixin
327
+ if (typeof mode.mixin.create !== 'function') {
328
+ throw new Error('Required function "create" missing on mixin');
329
+ }
330
+ var reserved = ['setMode', 'registerMode', 'modes'];
331
+ for (i = 0; i < reserved.length; i++) {
332
+ prop = reserved[i];
333
+ if (prop in mode.mixin) {
334
+ throw new Error('Reserved property "' + prop + '" not allowed in mixin');
335
+ }
336
+ }
337
+
338
+ JSONEditor.modes[name] = mode;
339
+ }
340
+ };
341
+
342
+ // register tree and text modes
343
+ JSONEditor.registerMode(treemode);
344
+ JSONEditor.registerMode(textmode);
345
+
346
+ module.exports = JSONEditor;
347
+
348
+
349
+ /***/ },
350
+ /* 1 */
351
+ /***/ function(module, exports, __webpack_require__) {
352
+
353
+ var Highlighter = __webpack_require__(4);
354
+ var History = __webpack_require__(5);
355
+ var SearchBox = __webpack_require__(6);
356
+ var Node = __webpack_require__(7);
357
+ var modeswitcher = __webpack_require__(8);
358
+ var util = __webpack_require__(3);
359
+
360
+ // create a mixin with the functions for tree mode
361
+ var treemode = {};
362
+
363
+ /**
364
+ * Create a tree editor
365
+ * @param {Element} container Container element
366
+ * @param {Object} [options] Object with options. available options:
367
+ * {String} mode Editor mode. Available values:
368
+ * 'tree' (default), 'view',
369
+ * and 'form'.
370
+ * {Boolean} search Enable search box.
371
+ * True by default
372
+ * {Boolean} history Enable history (undo/redo).
373
+ * True by default
374
+ * {function} change Callback method, triggered
375
+ * on change of contents
376
+ * {String} name Field name for the root node.
377
+ * @private
378
+ */
379
+ treemode.create = function (container, options) {
380
+ if (!container) {
381
+ throw new Error('No container element provided.');
382
+ }
383
+ this.container = container;
384
+ this.dom = {};
385
+ this.highlighter = new Highlighter();
386
+ this.selection = undefined; // will hold the last input selection
387
+
388
+ this._setOptions(options);
389
+
390
+ if (this.options.history && this.options.mode !== 'view') {
391
+ this.history = new History(this);
392
+ }
393
+
394
+ this._createFrame();
395
+ this._createTable();
396
+ };
397
+
398
+ /**
399
+ * Detach the editor from the DOM
400
+ * @private
401
+ */
402
+ treemode._delete = function () {
403
+ if (this.frame && this.container && this.frame.parentNode == this.container) {
404
+ this.container.removeChild(this.frame);
405
+ }
406
+ };
407
+
408
+ /**
409
+ * Initialize and set default options
410
+ * @param {Object} [options] See description in constructor
411
+ * @private
412
+ */
413
+ treemode._setOptions = function (options) {
414
+ this.options = {
415
+ search: true,
416
+ history: true,
417
+ mode: 'tree',
418
+ name: undefined // field name of root node
419
+ };
420
+
421
+ // copy all options
422
+ if (options) {
423
+ for (var prop in options) {
424
+ if (options.hasOwnProperty(prop)) {
425
+ this.options[prop] = options[prop];
426
+ }
427
+ }
428
+ }
429
+ };
430
+
431
+ // node currently being edited
432
+ var focusNode = undefined;
433
+
434
+ // dom having focus
435
+ var domFocus = null;
436
+
437
+ /**
438
+ * Set JSON object in editor
439
+ * @param {Object | undefined} json JSON data
440
+ * @param {String} [name] Optional field name for the root node.
441
+ * Can also be set using setName(name).
442
+ */
443
+ treemode.set = function (json, name) {
444
+ // adjust field name for root node
445
+ if (name) {
446
+ // TODO: deprecated since version 2.2.0. Cleanup some day.
447
+ util.log('Warning: second parameter "name" is deprecated. ' +
448
+ 'Use setName(name) instead.');
449
+ this.options.name = name;
450
+ }
451
+
452
+ // verify if json is valid JSON, ignore when a function
453
+ if (json instanceof Function || (json === undefined)) {
454
+ this.clear();
455
+ }
456
+ else {
457
+ this.content.removeChild(this.table); // Take the table offline
458
+
459
+ // replace the root node
460
+ var params = {
461
+ 'field': this.options.name,
462
+ 'value': json
463
+ };
464
+ var node = new Node(this, params);
465
+ this._setRoot(node);
466
+
467
+ // expand
468
+ var recurse = false;
469
+ this.node.expand(recurse);
470
+
471
+ this.content.appendChild(this.table); // Put the table online again
472
+ }
473
+
474
+ // TODO: maintain history, store last state and previous document
475
+ if (this.history) {
476
+ this.history.clear();
477
+ }
478
+ };
479
+
480
+ /**
481
+ * Get JSON object from editor
482
+ * @return {Object | undefined} json
483
+ */
484
+ treemode.get = function () {
485
+ // remove focus from currently edited node
486
+ if (focusNode) {
487
+ focusNode.blur();
488
+ }
489
+
490
+ if (this.node) {
491
+ return this.node.getValue();
492
+ }
493
+ else {
494
+ return undefined;
495
+ }
496
+ };
497
+
498
+ /**
499
+ * Get the text contents of the editor
500
+ * @return {String} jsonText
501
+ */
502
+ treemode.getText = function() {
503
+ return JSON.stringify(this.get());
504
+ };
505
+
506
+ /**
507
+ * Set the text contents of the editor
508
+ * @param {String} jsonText
509
+ */
510
+ treemode.setText = function(jsonText) {
511
+ this.set(util.parse(jsonText));
512
+ };
513
+
514
+ /**
515
+ * Set a field name for the root node.
516
+ * @param {String | undefined} name
517
+ */
518
+ treemode.setName = function (name) {
519
+ this.options.name = name;
520
+ if (this.node) {
521
+ this.node.updateField(this.options.name);
522
+ }
523
+ };
524
+
525
+ /**
526
+ * Get the field name for the root node.
527
+ * @return {String | undefined} name
528
+ */
529
+ treemode.getName = function () {
530
+ return this.options.name;
531
+ };
532
+
533
+ /**
534
+ * Set focus to the editor. Focus will be set to:
535
+ * - the first editable field or value, or else
536
+ * - to the expand button of the root node, or else
537
+ * - to the context menu button of the root node, or else
538
+ * - to the first button in the top menu
539
+ */
540
+ treemode.focus = function () {
541
+ var input = this.content.querySelector('[contenteditable=true]');
542
+ if (input) {
543
+ input.focus();
544
+ }
545
+ else if (this.node.dom.expand) {
546
+ this.node.dom.expand.focus();
547
+ }
548
+ else if (this.node.dom.menu) {
549
+ this.node.dom.menu.focus();
550
+ }
551
+ else {
552
+ // focus to the first button in the menu
553
+ input = this.frame.querySelector('button');
554
+ if (input) {
555
+ input.focus();
556
+ }
557
+ }
558
+ };
559
+
560
+ /**
561
+ * Remove the root node from the editor
562
+ */
563
+ treemode.clear = function () {
564
+ if (this.node) {
565
+ this.node.collapse();
566
+ this.tbody.removeChild(this.node.getDom());
567
+ delete this.node;
568
+ }
569
+ };
570
+
571
+ /**
572
+ * Set the root node for the json editor
573
+ * @param {Node} node
574
+ * @private
575
+ */
576
+ treemode._setRoot = function (node) {
577
+ this.clear();
578
+
579
+ this.node = node;
580
+
581
+ // append to the dom
582
+ this.tbody.appendChild(node.getDom());
583
+ };
584
+
585
+ /**
586
+ * Search text in all nodes
587
+ * The nodes will be expanded when the text is found one of its childs,
588
+ * else it will be collapsed. Searches are case insensitive.
589
+ * @param {String} text
590
+ * @return {Object[]} results Array with nodes containing the search results
591
+ * The result objects contains fields:
592
+ * - {Node} node,
593
+ * - {String} elem the dom element name where
594
+ * the result is found ('field' or
595
+ * 'value')
596
+ */
597
+ treemode.search = function (text) {
598
+ var results;
599
+ if (this.node) {
600
+ this.content.removeChild(this.table); // Take the table offline
601
+ results = this.node.search(text);
602
+ this.content.appendChild(this.table); // Put the table online again
603
+ }
604
+ else {
605
+ results = [];
606
+ }
607
+
608
+ return results;
609
+ };
610
+
611
+ /**
612
+ * Expand all nodes
613
+ */
614
+ treemode.expandAll = function () {
615
+ if (this.node) {
616
+ this.content.removeChild(this.table); // Take the table offline
617
+ this.node.expand();
618
+ this.content.appendChild(this.table); // Put the table online again
619
+ }
620
+ };
621
+
622
+ /**
623
+ * Collapse all nodes
624
+ */
625
+ treemode.collapseAll = function () {
626
+ if (this.node) {
627
+ this.content.removeChild(this.table); // Take the table offline
628
+ this.node.collapse();
629
+ this.content.appendChild(this.table); // Put the table online again
630
+ }
631
+ };
632
+
633
+ /**
634
+ * The method onChange is called whenever a field or value is changed, created,
635
+ * deleted, duplicated, etc.
636
+ * @param {String} action Change action. Available values: "editField",
637
+ * "editValue", "changeType", "appendNode",
638
+ * "removeNode", "duplicateNode", "moveNode", "expand",
639
+ * "collapse".
640
+ * @param {Object} params Object containing parameters describing the change.
641
+ * The parameters in params depend on the action (for
642
+ * example for "editValue" the Node, old value, and new
643
+ * value are provided). params contains all information
644
+ * needed to undo or redo the action.
645
+ * @private
646
+ */
647
+ treemode._onAction = function (action, params) {
648
+ // add an action to the history
649
+ if (this.history) {
650
+ this.history.add(action, params);
651
+ }
652
+
653
+ // trigger the onChange callback
654
+ if (this.options.change) {
655
+ try {
656
+ this.options.change();
657
+ }
658
+ catch (err) {
659
+ util.log('Error in change callback: ', err);
660
+ }
661
+ }
662
+ };
663
+
664
+ /**
665
+ * Start autoscrolling when given mouse position is above the top of the
666
+ * editor contents, or below the bottom.
667
+ * @param {Number} mouseY Absolute mouse position in pixels
668
+ */
669
+ treemode.startAutoScroll = function (mouseY) {
670
+ var me = this;
671
+ var content = this.content;
672
+ var top = util.getAbsoluteTop(content);
673
+ var height = content.clientHeight;
674
+ var bottom = top + height;
675
+ var margin = 24;
676
+ var interval = 50; // ms
677
+
678
+ if ((mouseY < top + margin) && content.scrollTop > 0) {
679
+ this.autoScrollStep = ((top + margin) - mouseY) / 3;
680
+ }
681
+ else if (mouseY > bottom - margin &&
682
+ height + content.scrollTop < content.scrollHeight) {
683
+ this.autoScrollStep = ((bottom - margin) - mouseY) / 3;
684
+ }
685
+ else {
686
+ this.autoScrollStep = undefined;
687
+ }
688
+
689
+ if (this.autoScrollStep) {
690
+ if (!this.autoScrollTimer) {
691
+ this.autoScrollTimer = setInterval(function () {
692
+ if (me.autoScrollStep) {
693
+ content.scrollTop -= me.autoScrollStep;
694
+ }
695
+ else {
696
+ me.stopAutoScroll();
697
+ }
698
+ }, interval);
699
+ }
700
+ }
701
+ else {
702
+ this.stopAutoScroll();
703
+ }
704
+ };
705
+
706
+ /**
707
+ * Stop auto scrolling. Only applicable when scrolling
708
+ */
709
+ treemode.stopAutoScroll = function () {
710
+ if (this.autoScrollTimer) {
711
+ clearTimeout(this.autoScrollTimer);
712
+ delete this.autoScrollTimer;
713
+ }
714
+ if (this.autoScrollStep) {
715
+ delete this.autoScrollStep;
716
+ }
717
+ };
718
+
719
+
720
+ /**
721
+ * Set the focus to an element in the editor, set text selection, and
722
+ * set scroll position.
723
+ * @param {Object} selection An object containing fields:
724
+ * {Element | undefined} dom The dom element
725
+ * which has focus
726
+ * {Range | TextRange} range A text selection
727
+ * {Number} scrollTop Scroll position
728
+ */
729
+ treemode.setSelection = function (selection) {
730
+ if (!selection) {
731
+ return;
732
+ }
733
+
734
+ if ('scrollTop' in selection && this.content) {
735
+ // TODO: animated scroll
736
+ this.content.scrollTop = selection.scrollTop;
737
+ }
738
+ if (selection.range) {
739
+ util.setSelectionOffset(selection.range);
740
+ }
741
+ if (selection.dom) {
742
+ selection.dom.focus();
743
+ }
744
+ };
745
+
746
+ /**
747
+ * Get the current focus
748
+ * @return {Object} selection An object containing fields:
749
+ * {Element | undefined} dom The dom element
750
+ * which has focus
751
+ * {Range | TextRange} range A text selection
752
+ * {Number} scrollTop Scroll position
753
+ */
754
+ treemode.getSelection = function () {
755
+ return {
756
+ dom: domFocus,
757
+ scrollTop: this.content ? this.content.scrollTop : 0,
758
+ range: util.getSelectionOffset()
759
+ };
760
+ };
761
+
762
+ /**
763
+ * Adjust the scroll position such that given top position is shown at 1/4
764
+ * of the window height.
765
+ * @param {Number} top
766
+ * @param {function(boolean)} [callback] Callback, executed when animation is
767
+ * finished. The callback returns true
768
+ * when animation is finished, or false
769
+ * when not.
770
+ */
771
+ treemode.scrollTo = function (top, callback) {
772
+ var content = this.content;
773
+ if (content) {
774
+ var editor = this;
775
+ // cancel any running animation
776
+ if (editor.animateTimeout) {
777
+ clearTimeout(editor.animateTimeout);
778
+ delete editor.animateTimeout;
779
+ }
780
+ if (editor.animateCallback) {
781
+ editor.animateCallback(false);
782
+ delete editor.animateCallback;
783
+ }
784
+
785
+ // calculate final scroll position
786
+ var height = content.clientHeight;
787
+ var bottom = content.scrollHeight - height;
788
+ var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom);
789
+
790
+ // animate towards the new scroll position
791
+ var animate = function () {
792
+ var scrollTop = content.scrollTop;
793
+ var diff = (finalScrollTop - scrollTop);
794
+ if (Math.abs(diff) > 3) {
795
+ content.scrollTop += diff / 3;
796
+ editor.animateCallback = callback;
797
+ editor.animateTimeout = setTimeout(animate, 50);
798
+ }
799
+ else {
800
+ // finished
801
+ if (callback) {
802
+ callback(true);
803
+ }
804
+ content.scrollTop = finalScrollTop;
805
+ delete editor.animateTimeout;
806
+ delete editor.animateCallback;
807
+ }
808
+ };
809
+ animate();
810
+ }
811
+ else {
812
+ if (callback) {
813
+ callback(false);
814
+ }
815
+ }
816
+ };
817
+
818
+ /**
819
+ * Create main frame
820
+ * @private
821
+ */
822
+ treemode._createFrame = function () {
823
+ // create the frame
824
+ this.frame = document.createElement('div');
825
+ this.frame.className = 'jsoneditor';
826
+ this.container.appendChild(this.frame);
827
+
828
+ // create one global event listener to handle all events from all nodes
829
+ var editor = this;
830
+ function onEvent(event) {
831
+ editor._onEvent(event);
832
+ }
833
+ this.frame.onclick = function (event) {
834
+ var target = event.target;// || event.srcElement;
835
+
836
+ onEvent(event);
837
+
838
+ // prevent default submit action of buttons when editor is located
839
+ // inside a form
840
+ if (target.nodeName == 'BUTTON') {
841
+ event.preventDefault();
842
+ }
843
+ };
844
+ this.frame.oninput = onEvent;
845
+ this.frame.onchange = onEvent;
846
+ this.frame.onkeydown = onEvent;
847
+ this.frame.onkeyup = onEvent;
848
+ this.frame.oncut = onEvent;
849
+ this.frame.onpaste = onEvent;
850
+ this.frame.onmousedown = onEvent;
851
+ this.frame.onmouseup = onEvent;
852
+ this.frame.onmouseover = onEvent;
853
+ this.frame.onmouseout = onEvent;
854
+ // Note: focus and blur events do not propagate, therefore they defined
855
+ // using an eventListener with useCapture=true
856
+ // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
857
+ util.addEventListener(this.frame, 'focus', onEvent, true);
858
+ util.addEventListener(this.frame, 'blur', onEvent, true);
859
+ this.frame.onfocusin = onEvent; // for IE
860
+ this.frame.onfocusout = onEvent; // for IE
861
+
862
+ // create menu
863
+ this.menu = document.createElement('div');
864
+ this.menu.className = 'menu';
865
+ this.frame.appendChild(this.menu);
866
+
867
+ // create expand all button
868
+ var expandAll = document.createElement('button');
869
+ expandAll.className = 'expand-all';
870
+ expandAll.title = 'Expand all fields';
871
+ expandAll.onclick = function () {
872
+ editor.expandAll();
873
+ };
874
+ this.menu.appendChild(expandAll);
875
+
876
+ // create expand all button
877
+ var collapseAll = document.createElement('button');
878
+ collapseAll.title = 'Collapse all fields';
879
+ collapseAll.className = 'collapse-all';
880
+ collapseAll.onclick = function () {
881
+ editor.collapseAll();
882
+ };
883
+ this.menu.appendChild(collapseAll);
884
+
885
+ // create undo/redo buttons
886
+ if (this.history) {
887
+ // create undo button
888
+ var undo = document.createElement('button');
889
+ undo.className = 'undo separator';
890
+ undo.title = 'Undo last action (Ctrl+Z)';
891
+ undo.onclick = function () {
892
+ editor._onUndo();
893
+ };
894
+ this.menu.appendChild(undo);
895
+ this.dom.undo = undo;
896
+
897
+ // create redo button
898
+ var redo = document.createElement('button');
899
+ redo.className = 'redo';
900
+ redo.title = 'Redo (Ctrl+Shift+Z)';
901
+ redo.onclick = function () {
902
+ editor._onRedo();
903
+ };
904
+ this.menu.appendChild(redo);
905
+ this.dom.redo = redo;
906
+
907
+ // register handler for onchange of history
908
+ this.history.onChange = function () {
909
+ undo.disabled = !editor.history.canUndo();
910
+ redo.disabled = !editor.history.canRedo();
911
+ };
912
+ this.history.onChange();
913
+ }
914
+
915
+ // create mode box
916
+ if (this.options && this.options.modes && this.options.modes.length) {
917
+ var modeBox = modeswitcher.create(this, this.options.modes, this.options.mode);
918
+ this.menu.appendChild(modeBox);
919
+ this.dom.modeBox = modeBox;
920
+ }
921
+
922
+ // create search box
923
+ if (this.options.search) {
924
+ this.searchBox = new SearchBox(this, this.menu);
925
+ }
926
+ };
927
+
928
+ /**
929
+ * Perform an undo action
930
+ * @private
931
+ */
932
+ treemode._onUndo = function () {
933
+ if (this.history) {
934
+ // undo last action
935
+ this.history.undo();
936
+
937
+ // trigger change callback
938
+ if (this.options.change) {
939
+ this.options.change();
940
+ }
941
+ }
942
+ };
943
+
944
+ /**
945
+ * Perform a redo action
946
+ * @private
947
+ */
948
+ treemode._onRedo = function () {
949
+ if (this.history) {
950
+ // redo last action
951
+ this.history.redo();
952
+
953
+ // trigger change callback
954
+ if (this.options.change) {
955
+ this.options.change();
956
+ }
957
+ }
958
+ };
959
+
960
+ /**
961
+ * Event handler
962
+ * @param event
963
+ * @private
964
+ */
965
+ treemode._onEvent = function (event) {
966
+ var target = event.target;
967
+
968
+ if (event.type == 'keydown') {
969
+ this._onKeyDown(event);
970
+ }
971
+
972
+ if (event.type == 'focus') {
973
+ domFocus = target;
974
+ }
975
+
976
+ var node = Node.getNodeFromTarget(target);
977
+ if (node) {
978
+ node.onEvent(event);
979
+ }
980
+ };
981
+
982
+ /**
983
+ * Event handler for keydown. Handles shortcut keys
984
+ * @param {Event} event
985
+ * @private
986
+ */
987
+ treemode._onKeyDown = function (event) {
988
+ var keynum = event.which || event.keyCode;
989
+ var ctrlKey = event.ctrlKey;
990
+ var shiftKey = event.shiftKey;
991
+ var handled = false;
992
+
993
+ if (keynum == 9) { // Tab or Shift+Tab
994
+ setTimeout(function () {
995
+ // select all text when moving focus to an editable div
996
+ util.selectContentEditable(domFocus);
997
+ }, 0);
998
+ }
999
+
1000
+ if (this.searchBox) {
1001
+ if (ctrlKey && keynum == 70) { // Ctrl+F
1002
+ this.searchBox.dom.search.focus();
1003
+ this.searchBox.dom.search.select();
1004
+ handled = true;
1005
+ }
1006
+ else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G
1007
+ var focus = true;
1008
+ if (!shiftKey) {
1009
+ // select next search result (F3 or Ctrl+G)
1010
+ this.searchBox.next(focus);
1011
+ }
1012
+ else {
1013
+ // select previous search result (Shift+F3 or Ctrl+Shift+G)
1014
+ this.searchBox.previous(focus);
1015
+ }
1016
+
1017
+ handled = true;
1018
+ }
1019
+ }
1020
+
1021
+ if (this.history) {
1022
+ if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z
1023
+ // undo
1024
+ this._onUndo();
1025
+ handled = true;
1026
+ }
1027
+ else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z
1028
+ // redo
1029
+ this._onRedo();
1030
+ handled = true;
1031
+ }
1032
+ }
1033
+
1034
+ if (handled) {
1035
+ event.preventDefault();
1036
+ event.stopPropagation();
1037
+ }
1038
+ };
1039
+
1040
+ /**
1041
+ * Create main table
1042
+ * @private
1043
+ */
1044
+ treemode._createTable = function () {
1045
+ var contentOuter = document.createElement('div');
1046
+ contentOuter.className = 'outer';
1047
+ this.contentOuter = contentOuter;
1048
+
1049
+ this.content = document.createElement('div');
1050
+ this.content.className = 'tree';
1051
+ contentOuter.appendChild(this.content);
1052
+
1053
+ this.table = document.createElement('table');
1054
+ this.table.className = 'tree';
1055
+ this.content.appendChild(this.table);
1056
+
1057
+ // create colgroup where the first two columns don't have a fixed
1058
+ // width, and the edit columns do have a fixed width
1059
+ var col;
1060
+ this.colgroupContent = document.createElement('colgroup');
1061
+ if (this.options.mode === 'tree') {
1062
+ col = document.createElement('col');
1063
+ col.width = "24px";
1064
+ this.colgroupContent.appendChild(col);
1065
+ }
1066
+ col = document.createElement('col');
1067
+ col.width = "24px";
1068
+ this.colgroupContent.appendChild(col);
1069
+ col = document.createElement('col');
1070
+ this.colgroupContent.appendChild(col);
1071
+ this.table.appendChild(this.colgroupContent);
1072
+
1073
+ this.tbody = document.createElement('tbody');
1074
+ this.table.appendChild(this.tbody);
1075
+
1076
+ this.frame.appendChild(contentOuter);
1077
+ };
1078
+
1079
+ // define modes
1080
+ module.exports = [
1081
+ {
1082
+ mode: 'tree',
1083
+ mixin: treemode,
1084
+ data: 'json'
1085
+ },
1086
+ {
1087
+ mode: 'view',
1088
+ mixin: treemode,
1089
+ data: 'json'
1090
+ },
1091
+ {
1092
+ mode: 'form',
1093
+ mixin: treemode,
1094
+ data: 'json'
1095
+ }
1096
+ ];
1097
+
1098
+ /***/ },
1099
+ /* 2 */
1100
+ /***/ function(module, exports, __webpack_require__) {
1101
+
1102
+ var ace;
1103
+ try {
1104
+ ace = __webpack_require__(9);
1105
+ }
1106
+ catch (err) {
1107
+ // failed to load ace, no problem, we will fall back to plain text
1108
+ }
1109
+
1110
+ var modeswitcher = __webpack_require__(8);
1111
+ var util = __webpack_require__(3);
1112
+
1113
+ // create a mixin with the functions for text mode
1114
+ var textmode = {};
1115
+
1116
+ /**
1117
+ * Create a text editor
1118
+ * @param {Element} container
1119
+ * @param {Object} [options] Object with options. available options:
1120
+ * {String} mode Available values:
1121
+ * "text" (default)
1122
+ * or "code".
1123
+ * {Number} indentation Number of indentation
1124
+ * spaces. 2 by default.
1125
+ * {function} change Callback method
1126
+ * triggered on change
1127
+ * @private
1128
+ */
1129
+ textmode.create = function (container, options) {
1130
+ // read options
1131
+ options = options || {};
1132
+ this.options = options;
1133
+ if (options.indentation) {
1134
+ this.indentation = Number(options.indentation);
1135
+ }
1136
+ else {
1137
+ this.indentation = 2; // number of spaces
1138
+ }
1139
+ this.mode = (options.mode == 'code') ? 'code' : 'text';
1140
+ if (this.mode == 'code') {
1141
+ // verify whether Ace editor is available and supported
1142
+ if (typeof ace === 'undefined') {
1143
+ this.mode = 'text';
1144
+ util.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
1145
+ 'Falling back to plain text editor');
1146
+ }
1147
+ }
1148
+
1149
+ var me = this;
1150
+ this.container = container;
1151
+ this.dom = {};
1152
+ this.editor = undefined; // ace code editor
1153
+ this.textarea = undefined; // plain text editor (fallback when Ace is not available)
1154
+
1155
+ this.width = container.clientWidth;
1156
+ this.height = container.clientHeight;
1157
+
1158
+ this.frame = document.createElement('div');
1159
+ this.frame.className = 'jsoneditor';
1160
+ this.frame.onclick = function (event) {
1161
+ // prevent default submit action when the editor is located inside a form
1162
+ event.preventDefault();
1163
+ };
1164
+ this.frame.onkeydown = function (event) {
1165
+ me._onKeyDown(event);
1166
+ };
1167
+
1168
+ // create menu
1169
+ this.menu = document.createElement('div');
1170
+ this.menu.className = 'menu';
1171
+ this.frame.appendChild(this.menu);
1172
+
1173
+ // create format button
1174
+ var buttonFormat = document.createElement('button');
1175
+ buttonFormat.className = 'format';
1176
+ buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)';
1177
+ this.menu.appendChild(buttonFormat);
1178
+ buttonFormat.onclick = function () {
1179
+ try {
1180
+ me.format();
1181
+ }
1182
+ catch (err) {
1183
+ me._onError(err);
1184
+ }
1185
+ };
1186
+
1187
+ // create compact button
1188
+ var buttonCompact = document.createElement('button');
1189
+ buttonCompact.className = 'compact';
1190
+ buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)';
1191
+ this.menu.appendChild(buttonCompact);
1192
+ buttonCompact.onclick = function () {
1193
+ try {
1194
+ me.compact();
1195
+ }
1196
+ catch (err) {
1197
+ me._onError(err);
1198
+ }
1199
+ };
1200
+
1201
+ // create mode box
1202
+ if (this.options && this.options.modes && this.options.modes.length) {
1203
+ var modeBox = modeswitcher.create(this, this.options.modes, this.options.mode);
1204
+ this.menu.appendChild(modeBox);
1205
+ this.dom.modeBox = modeBox;
1206
+ }
1207
+
1208
+ this.content = document.createElement('div');
1209
+ this.content.className = 'outer';
1210
+ this.frame.appendChild(this.content);
1211
+
1212
+ this.container.appendChild(this.frame);
1213
+
1214
+ if (this.mode == 'code') {
1215
+ this.editorDom = document.createElement('div');
1216
+ this.editorDom.style.height = '100%'; // TODO: move to css
1217
+ this.editorDom.style.width = '100%'; // TODO: move to css
1218
+ this.content.appendChild(this.editorDom);
1219
+
1220
+ var editor = ace.edit(this.editorDom);
1221
+ editor.setTheme('ace/theme/jsoneditor');
1222
+ editor.setShowPrintMargin(false);
1223
+ editor.setFontSize(13);
1224
+ editor.getSession().setMode('ace/mode/json');
1225
+ editor.getSession().setTabSize(this.indentation);
1226
+ editor.getSession().setUseSoftTabs(true);
1227
+ editor.getSession().setUseWrapMode(true);
1228
+ this.editor = editor;
1229
+
1230
+ var poweredBy = document.createElement('a');
1231
+ poweredBy.appendChild(document.createTextNode('powered by ace'));
1232
+ poweredBy.href = 'http://ace.ajax.org';
1233
+ poweredBy.target = '_blank';
1234
+ poweredBy.className = 'poweredBy';
1235
+ poweredBy.onclick = function () {
1236
+ // TODO: this anchor falls below the margin of the content,
1237
+ // therefore the normal a.href does not work. We use a click event
1238
+ // for now, but this should be fixed.
1239
+ window.open(poweredBy.href, poweredBy.target);
1240
+ };
1241
+ this.menu.appendChild(poweredBy);
1242
+
1243
+ if (options.change) {
1244
+ // register onchange event
1245
+ editor.on('change', function () {
1246
+ options.change();
1247
+ });
1248
+ }
1249
+ }
1250
+ else {
1251
+ // load a plain text textarea
1252
+ var textarea = document.createElement('textarea');
1253
+ textarea.className = 'text';
1254
+ textarea.spellcheck = false;
1255
+ this.content.appendChild(textarea);
1256
+ this.textarea = textarea;
1257
+
1258
+ if (options.change) {
1259
+ // register onchange event
1260
+ if (this.textarea.oninput === null) {
1261
+ this.textarea.oninput = function () {
1262
+ options.change();
1263
+ }
1264
+ }
1265
+ else {
1266
+ // oninput is undefined. For IE8-
1267
+ this.textarea.onchange = function () {
1268
+ options.change();
1269
+ }
1270
+ }
1271
+ }
1272
+ }
1273
+ };
1274
+
1275
+ /**
1276
+ * Event handler for keydown. Handles shortcut keys
1277
+ * @param {Event} event
1278
+ * @private
1279
+ */
1280
+ textmode._onKeyDown = function (event) {
1281
+ var keynum = event.which || event.keyCode;
1282
+ var handled = false;
1283
+
1284
+ if (keynum == 220 && event.ctrlKey) {
1285
+ if (event.shiftKey) { // Ctrl+Shift+\
1286
+ this.compact();
1287
+ }
1288
+ else { // Ctrl+\
1289
+ this.format();
1290
+ }
1291
+ handled = true;
1292
+ }
1293
+
1294
+ if (handled) {
1295
+ event.preventDefault();
1296
+ event.stopPropagation();
1297
+ }
1298
+ };
1299
+
1300
+ /**
1301
+ * Detach the editor from the DOM
1302
+ * @private
1303
+ */
1304
+ textmode._delete = function () {
1305
+ if (this.frame && this.container && this.frame.parentNode == this.container) {
1306
+ this.container.removeChild(this.frame);
1307
+ }
1308
+ };
1309
+
1310
+ /**
1311
+ * Throw an error. If an error callback is configured in options.error, this
1312
+ * callback will be invoked. Else, a regular error is thrown.
1313
+ * @param {Error} err
1314
+ * @private
1315
+ */
1316
+ textmode._onError = function(err) {
1317
+ // TODO: onError is deprecated since version 2.2.0. cleanup some day
1318
+ if (typeof this.onError === 'function') {
1319
+ util.log('WARNING: JSONEditor.onError is deprecated. ' +
1320
+ 'Use options.error instead.');
1321
+ this.onError(err);
1322
+ }
1323
+
1324
+ if (this.options && typeof this.options.error === 'function') {
1325
+ this.options.error(err);
1326
+ }
1327
+ else {
1328
+ throw err;
1329
+ }
1330
+ };
1331
+
1332
+ /**
1333
+ * Compact the code in the formatter
1334
+ */
1335
+ textmode.compact = function () {
1336
+ var json = this.get();
1337
+ var text = JSON.stringify(json);
1338
+ this.setText(text);
1339
+ };
1340
+
1341
+ /**
1342
+ * Format the code in the formatter
1343
+ */
1344
+ textmode.format = function () {
1345
+ var json = this.get();
1346
+ var text = JSON.stringify(json, null, this.indentation);
1347
+ this.setText(text);
1348
+ };
1349
+
1350
+ /**
1351
+ * Set focus to the formatter
1352
+ */
1353
+ textmode.focus = function () {
1354
+ if (this.textarea) {
1355
+ this.textarea.focus();
1356
+ }
1357
+ if (this.editor) {
1358
+ this.editor.focus();
1359
+ }
1360
+ };
1361
+
1362
+ /**
1363
+ * Resize the formatter
1364
+ */
1365
+ textmode.resize = function () {
1366
+ if (this.editor) {
1367
+ var force = false;
1368
+ this.editor.resize(force);
1369
+ }
1370
+ };
1371
+
1372
+ /**
1373
+ * Set json data in the formatter
1374
+ * @param {Object} json
1375
+ */
1376
+ textmode.set = function(json) {
1377
+ this.setText(JSON.stringify(json, null, this.indentation));
1378
+ };
1379
+
1380
+ /**
1381
+ * Get json data from the formatter
1382
+ * @return {Object} json
1383
+ */
1384
+ textmode.get = function() {
1385
+ var text = this.getText();
1386
+ var json;
1387
+
1388
+ try {
1389
+ json = util.parse(text); // this can throw an error
1390
+ }
1391
+ catch (err) {
1392
+ // try to sanitize json, replace JavaScript notation with JSON notation
1393
+ text = util.sanitize(text);
1394
+ this.setText(text);
1395
+
1396
+ // try to parse again
1397
+ json = util.parse(text); // this can throw an error
1398
+ }
1399
+
1400
+ return json;
1401
+ };
1402
+
1403
+ /**
1404
+ * Get the text contents of the editor
1405
+ * @return {String} jsonText
1406
+ */
1407
+ textmode.getText = function() {
1408
+ if (this.textarea) {
1409
+ return this.textarea.value;
1410
+ }
1411
+ if (this.editor) {
1412
+ return this.editor.getValue();
1413
+ }
1414
+ return '';
1415
+ };
1416
+
1417
+ /**
1418
+ * Set the text contents of the editor
1419
+ * @param {String} jsonText
1420
+ */
1421
+ textmode.setText = function(jsonText) {
1422
+ if (this.textarea) {
1423
+ this.textarea.value = jsonText;
1424
+ }
1425
+ if (this.editor) {
1426
+ this.editor.setValue(jsonText, -1);
1427
+ }
1428
+ };
1429
+
1430
+ // define modes
1431
+ module.exports = [
1432
+ {
1433
+ mode: 'text',
1434
+ mixin: textmode,
1435
+ data: 'text',
1436
+ load: textmode.format
1437
+ },
1438
+ {
1439
+ mode: 'code',
1440
+ mixin: textmode,
1441
+ data: 'text',
1442
+ load: textmode.format
1443
+ }
1444
+ ];
1445
+
1446
+
1447
+ /***/ },
1448
+ /* 3 */
1449
+ /***/ function(module, exports, __webpack_require__) {
1450
+
1451
+ var jsonlint = __webpack_require__(12);
1452
+
1453
+ /**
1454
+ * Parse JSON using the parser built-in in the browser.
1455
+ * On exception, the jsonString is validated and a detailed error is thrown.
1456
+ * @param {String} jsonString
1457
+ * @return {JSON} json
1458
+ */
1459
+ exports.parse = function parse(jsonString) {
1460
+ try {
1461
+ return JSON.parse(jsonString);
1462
+ }
1463
+ catch (err) {
1464
+ // try to throw a more detailed error message using validate
1465
+ exports.validate(jsonString);
1466
+
1467
+ // rethrow the original error
1468
+ throw err;
1469
+ }
1470
+ };
1471
+
1472
+ /**
1473
+ * Sanitize a JSON-like string containing. For example changes JavaScript
1474
+ * notation into JSON notation.
1475
+ * This function for example changes a string like "{a: 2, 'b': {c: 'd'}"
1476
+ * into '{"a": 2, "b": {"c": "d"}'
1477
+ * @param {string} jsString
1478
+ * @returns {string} json
1479
+ */
1480
+ exports.sanitize = function (jsString) {
1481
+ // escape all single and double quotes inside strings
1482
+ var chars = [];
1483
+ var i = 0;
1484
+
1485
+ //If JSON starts with a function (characters/digits/"_-"), remove this function.
1486
+ //This is useful for "stripping" JSONP objects to become JSON
1487
+ //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}]
1488
+ var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/);
1489
+ if (match) {
1490
+ jsString = match[3];
1491
+ }
1492
+
1493
+ // helper functions to get the current/prev/next character
1494
+ function curr () { return jsString.charAt(i); }
1495
+ function next() { return jsString.charAt(i + 1); }
1496
+ function prev() { return jsString.charAt(i - 1); }
1497
+
1498
+ // test whether the last non-whitespace character was a brace-open '{'
1499
+ function prevIsBrace() {
1500
+ var ii = i - 1;
1501
+ while (ii >= 0) {
1502
+ var cc = jsString.charAt(ii);
1503
+ if (cc === '{') {
1504
+ return true;
1505
+ }
1506
+ else if (cc === ' ' || cc === '\n' || cc === '\r') { // whitespace
1507
+ ii--;
1508
+ }
1509
+ else {
1510
+ return false;
1511
+ }
1512
+ }
1513
+ return false;
1514
+ }
1515
+
1516
+ // skip a block comment '/* ... */'
1517
+ function skipComment () {
1518
+ i += 2;
1519
+ while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
1520
+ i++;
1521
+ }
1522
+ i += 2;
1523
+ }
1524
+
1525
+ // parse single or double quoted string
1526
+ function parseString(quote) {
1527
+ chars.push('"');
1528
+ i++;
1529
+ var c = curr();
1530
+ while (i < jsString.length && c !== quote) {
1531
+ if (c === '"' && prev() !== '\\') {
1532
+ // unescaped double quote, escape it
1533
+ chars.push('\\');
1534
+ }
1535
+
1536
+ // handle escape character
1537
+ if (c === '\\') {
1538
+ i++;
1539
+ c = curr();
1540
+
1541
+ // remove the escape character when followed by a single quote ', not needed
1542
+ if (c !== '\'') {
1543
+ chars.push('\\');
1544
+ }
1545
+ }
1546
+ chars.push(c);
1547
+
1548
+ i++;
1549
+ c = curr();
1550
+ }
1551
+ if (c === quote) {
1552
+ chars.push('"');
1553
+ i++;
1554
+ }
1555
+ }
1556
+
1557
+ // parse an unquoted key
1558
+ function parseKey() {
1559
+ var specialValues = ['null', 'true', 'false'];
1560
+ var key = '';
1561
+ var c = curr();
1562
+
1563
+ var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character
1564
+ while (regexp.test(c)) {
1565
+ key += c;
1566
+ i++;
1567
+ c = curr();
1568
+ }
1569
+
1570
+ if (specialValues.indexOf(key) === -1) {
1571
+ chars.push('"' + key + '"');
1572
+ }
1573
+ else {
1574
+ chars.push(key);
1575
+ }
1576
+ }
1577
+
1578
+ while(i < jsString.length) {
1579
+ var c = curr();
1580
+
1581
+ if (c === '/' && next() === '*') {
1582
+ skipComment();
1583
+ }
1584
+ else if (c === '\'' || c === '"') {
1585
+ parseString(c);
1586
+ }
1587
+ else if (/[a-zA-Z_$]/.test(c) && prevIsBrace()) {
1588
+ // an unquoted object key (like a in '{a:2}')
1589
+ parseKey();
1590
+ }
1591
+ else {
1592
+ chars.push(c);
1593
+ i++;
1594
+ }
1595
+ }
1596
+
1597
+ return chars.join('');
1598
+ };
1599
+
1600
+ /**
1601
+ * Validate a string containing a JSON object
1602
+ * This method uses JSONLint to validate the String. If JSONLint is not
1603
+ * available, the built-in JSON parser of the browser is used.
1604
+ * @param {String} jsonString String with an (invalid) JSON object
1605
+ * @throws Error
1606
+ */
1607
+ exports.validate = function validate(jsonString) {
1608
+ if (typeof(jsonlint) != 'undefined') {
1609
+ jsonlint.parse(jsonString);
1610
+ }
1611
+ else {
1612
+ JSON.parse(jsonString);
1613
+ }
1614
+ };
1615
+
1616
+ /**
1617
+ * Extend object a with the properties of object b
1618
+ * @param {Object} a
1619
+ * @param {Object} b
1620
+ * @return {Object} a
1621
+ */
1622
+ exports.extend = function extend(a, b) {
1623
+ for (var prop in b) {
1624
+ if (b.hasOwnProperty(prop)) {
1625
+ a[prop] = b[prop];
1626
+ }
1627
+ }
1628
+ return a;
1629
+ };
1630
+
1631
+ /**
1632
+ * Remove all properties from object a
1633
+ * @param {Object} a
1634
+ * @return {Object} a
1635
+ */
1636
+ exports.clear = function clear (a) {
1637
+ for (var prop in a) {
1638
+ if (a.hasOwnProperty(prop)) {
1639
+ delete a[prop];
1640
+ }
1641
+ }
1642
+ return a;
1643
+ };
1644
+
1645
+ /**
1646
+ * Output text to the console, if console is available
1647
+ * @param {...*} args
1648
+ */
1649
+ exports.log = function log (args) {
1650
+ if (typeof console !== 'undefined' && typeof console.log === 'function') {
1651
+ console.log.apply(console, arguments);
1652
+ }
1653
+ };
1654
+
1655
+ /**
1656
+ * Get the type of an object
1657
+ * @param {*} object
1658
+ * @return {String} type
1659
+ */
1660
+ exports.type = function type (object) {
1661
+ if (object === null) {
1662
+ return 'null';
1663
+ }
1664
+ if (object === undefined) {
1665
+ return 'undefined';
1666
+ }
1667
+ if ((object instanceof Number) || (typeof object === 'number')) {
1668
+ return 'number';
1669
+ }
1670
+ if ((object instanceof String) || (typeof object === 'string')) {
1671
+ return 'string';
1672
+ }
1673
+ if ((object instanceof Boolean) || (typeof object === 'boolean')) {
1674
+ return 'boolean';
1675
+ }
1676
+ if ((object instanceof RegExp) || (typeof object === 'regexp')) {
1677
+ return 'regexp';
1678
+ }
1679
+ if (exports.isArray(object)) {
1680
+ return 'array';
1681
+ }
1682
+
1683
+ return 'object';
1684
+ };
1685
+
1686
+ /**
1687
+ * Test whether a text contains a url (matches when a string starts
1688
+ * with 'http://*' or 'https://*' and has no whitespace characters)
1689
+ * @param {String} text
1690
+ */
1691
+ var isUrlRegex = /^https?:\/\/\S+$/;
1692
+ exports.isUrl = function isUrl (text) {
1693
+ return (typeof text == 'string' || text instanceof String) &&
1694
+ isUrlRegex.test(text);
1695
+ };
1696
+
1697
+ /**
1698
+ * Tes whether given object is an Array
1699
+ * @param {*} obj
1700
+ * @returns {boolean} returns true when obj is an array
1701
+ */
1702
+ exports.isArray = function (obj) {
1703
+ return Object.prototype.toString.call(obj) === '[object Array]';
1704
+ };
1705
+
1706
+ /**
1707
+ * Retrieve the absolute left value of a DOM element
1708
+ * @param {Element} elem A dom element, for example a div
1709
+ * @return {Number} left The absolute left position of this element
1710
+ * in the browser page.
1711
+ */
1712
+ exports.getAbsoluteLeft = function getAbsoluteLeft(elem) {
1713
+ var rect = elem.getBoundingClientRect();
1714
+ return rect.left + window.pageXOffset || document.scrollLeft || 0;
1715
+ };
1716
+
1717
+ /**
1718
+ * Retrieve the absolute top value of a DOM element
1719
+ * @param {Element} elem A dom element, for example a div
1720
+ * @return {Number} top The absolute top position of this element
1721
+ * in the browser page.
1722
+ */
1723
+ exports.getAbsoluteTop = function getAbsoluteTop(elem) {
1724
+ var rect = elem.getBoundingClientRect();
1725
+ return rect.top + window.pageYOffset || document.scrollTop || 0;
1726
+ };
1727
+
1728
+ /**
1729
+ * add a className to the given elements style
1730
+ * @param {Element} elem
1731
+ * @param {String} className
1732
+ */
1733
+ exports.addClassName = function addClassName(elem, className) {
1734
+ var classes = elem.className.split(' ');
1735
+ if (classes.indexOf(className) == -1) {
1736
+ classes.push(className); // add the class to the array
1737
+ elem.className = classes.join(' ');
1738
+ }
1739
+ };
1740
+
1741
+ /**
1742
+ * add a className to the given elements style
1743
+ * @param {Element} elem
1744
+ * @param {String} className
1745
+ */
1746
+ exports.removeClassName = function removeClassName(elem, className) {
1747
+ var classes = elem.className.split(' ');
1748
+ var index = classes.indexOf(className);
1749
+ if (index != -1) {
1750
+ classes.splice(index, 1); // remove the class from the array
1751
+ elem.className = classes.join(' ');
1752
+ }
1753
+ };
1754
+
1755
+ /**
1756
+ * Strip the formatting from the contents of a div
1757
+ * the formatting from the div itself is not stripped, only from its childs.
1758
+ * @param {Element} divElement
1759
+ */
1760
+ exports.stripFormatting = function stripFormatting(divElement) {
1761
+ var childs = divElement.childNodes;
1762
+ for (var i = 0, iMax = childs.length; i < iMax; i++) {
1763
+ var child = childs[i];
1764
+
1765
+ // remove the style
1766
+ if (child.style) {
1767
+ // TODO: test if child.attributes does contain style
1768
+ child.removeAttribute('style');
1769
+ }
1770
+
1771
+ // remove all attributes
1772
+ var attributes = child.attributes;
1773
+ if (attributes) {
1774
+ for (var j = attributes.length - 1; j >= 0; j--) {
1775
+ var attribute = attributes[j];
1776
+ if (attribute.specified === true) {
1777
+ child.removeAttribute(attribute.name);
1778
+ }
1779
+ }
1780
+ }
1781
+
1782
+ // recursively strip childs
1783
+ exports.stripFormatting(child);
1784
+ }
1785
+ };
1786
+
1787
+ /**
1788
+ * Set focus to the end of an editable div
1789
+ * code from Nico Burns
1790
+ * http://stackoverflow.com/users/140293/nico-burns
1791
+ * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity
1792
+ * @param {Element} contentEditableElement A content editable div
1793
+ */
1794
+ exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) {
1795
+ var range, selection;
1796
+ if(document.createRange) {
1797
+ range = document.createRange();//Create a range (a range is a like the selection but invisible)
1798
+ range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
1799
+ range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
1800
+ selection = window.getSelection();//get the selection object (allows you to change selection)
1801
+ selection.removeAllRanges();//remove any selections already made
1802
+ selection.addRange(range);//make the range you have just created the visible selection
1803
+ }
1804
+ };
1805
+
1806
+ /**
1807
+ * Select all text of a content editable div.
1808
+ * http://stackoverflow.com/a/3806004/1262753
1809
+ * @param {Element} contentEditableElement A content editable div
1810
+ */
1811
+ exports.selectContentEditable = function selectContentEditable(contentEditableElement) {
1812
+ if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') {
1813
+ return;
1814
+ }
1815
+
1816
+ var sel, range;
1817
+ if (window.getSelection && document.createRange) {
1818
+ range = document.createRange();
1819
+ range.selectNodeContents(contentEditableElement);
1820
+ sel = window.getSelection();
1821
+ sel.removeAllRanges();
1822
+ sel.addRange(range);
1823
+ }
1824
+ };
1825
+
1826
+ /**
1827
+ * Get text selection
1828
+ * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
1829
+ * @return {Range | TextRange | null} range
1830
+ */
1831
+ exports.getSelection = function getSelection() {
1832
+ if (window.getSelection) {
1833
+ var sel = window.getSelection();
1834
+ if (sel.getRangeAt && sel.rangeCount) {
1835
+ return sel.getRangeAt(0);
1836
+ }
1837
+ }
1838
+ return null;
1839
+ };
1840
+
1841
+ /**
1842
+ * Set text selection
1843
+ * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
1844
+ * @param {Range | TextRange | null} range
1845
+ */
1846
+ exports.setSelection = function setSelection(range) {
1847
+ if (range) {
1848
+ if (window.getSelection) {
1849
+ var sel = window.getSelection();
1850
+ sel.removeAllRanges();
1851
+ sel.addRange(range);
1852
+ }
1853
+ }
1854
+ };
1855
+
1856
+ /**
1857
+ * Get selected text range
1858
+ * @return {Object} params object containing parameters:
1859
+ * {Number} startOffset
1860
+ * {Number} endOffset
1861
+ * {Element} container HTML element holding the
1862
+ * selected text element
1863
+ * Returns null if no text selection is found
1864
+ */
1865
+ exports.getSelectionOffset = function getSelectionOffset() {
1866
+ var range = exports.getSelection();
1867
+
1868
+ if (range && 'startOffset' in range && 'endOffset' in range &&
1869
+ range.startContainer && (range.startContainer == range.endContainer)) {
1870
+ return {
1871
+ startOffset: range.startOffset,
1872
+ endOffset: range.endOffset,
1873
+ container: range.startContainer.parentNode
1874
+ };
1875
+ }
1876
+
1877
+ return null;
1878
+ };
1879
+
1880
+ /**
1881
+ * Set selected text range in given element
1882
+ * @param {Object} params An object containing:
1883
+ * {Element} container
1884
+ * {Number} startOffset
1885
+ * {Number} endOffset
1886
+ */
1887
+ exports.setSelectionOffset = function setSelectionOffset(params) {
1888
+ if (document.createRange && window.getSelection) {
1889
+ var selection = window.getSelection();
1890
+ if(selection) {
1891
+ var range = document.createRange();
1892
+ // TODO: do not suppose that the first child of the container is a textnode,
1893
+ // but recursively find the textnodes
1894
+ range.setStart(params.container.firstChild, params.startOffset);
1895
+ range.setEnd(params.container.firstChild, params.endOffset);
1896
+
1897
+ exports.setSelection(range);
1898
+ }
1899
+ }
1900
+ };
1901
+
1902
+ /**
1903
+ * Get the inner text of an HTML element (for example a div element)
1904
+ * @param {Element} element
1905
+ * @param {Object} [buffer]
1906
+ * @return {String} innerText
1907
+ */
1908
+ exports.getInnerText = function getInnerText(element, buffer) {
1909
+ var first = (buffer == undefined);
1910
+ if (first) {
1911
+ buffer = {
1912
+ 'text': '',
1913
+ 'flush': function () {
1914
+ var text = this.text;
1915
+ this.text = '';
1916
+ return text;
1917
+ },
1918
+ 'set': function (text) {
1919
+ this.text = text;
1920
+ }
1921
+ };
1922
+ }
1923
+
1924
+ // text node
1925
+ if (element.nodeValue) {
1926
+ return buffer.flush() + element.nodeValue;
1927
+ }
1928
+
1929
+ // divs or other HTML elements
1930
+ if (element.hasChildNodes()) {
1931
+ var childNodes = element.childNodes;
1932
+ var innerText = '';
1933
+
1934
+ for (var i = 0, iMax = childNodes.length; i < iMax; i++) {
1935
+ var child = childNodes[i];
1936
+
1937
+ if (child.nodeName == 'DIV' || child.nodeName == 'P') {
1938
+ var prevChild = childNodes[i - 1];
1939
+ var prevName = prevChild ? prevChild.nodeName : undefined;
1940
+ if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') {
1941
+ innerText += '\n';
1942
+ buffer.flush();
1943
+ }
1944
+ innerText += exports.getInnerText(child, buffer);
1945
+ buffer.set('\n');
1946
+ }
1947
+ else if (child.nodeName == 'BR') {
1948
+ innerText += buffer.flush();
1949
+ buffer.set('\n');
1950
+ }
1951
+ else {
1952
+ innerText += exports.getInnerText(child, buffer);
1953
+ }
1954
+ }
1955
+
1956
+ return innerText;
1957
+ }
1958
+ else {
1959
+ if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) {
1960
+ // On Internet Explorer, a <p> with hasChildNodes()==false is
1961
+ // rendered with a new line. Note that a <p> with
1962
+ // hasChildNodes()==true is rendered without a new line
1963
+ // Other browsers always ensure there is a <br> inside the <p>,
1964
+ // and if not, the <p> does not render a new line
1965
+ return buffer.flush();
1966
+ }
1967
+ }
1968
+
1969
+ // br or unknown
1970
+ return '';
1971
+ };
1972
+
1973
+ /**
1974
+ * Returns the version of Internet Explorer or a -1
1975
+ * (indicating the use of another browser).
1976
+ * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx
1977
+ * @return {Number} Internet Explorer version, or -1 in case of an other browser
1978
+ */
1979
+ exports.getInternetExplorerVersion = function getInternetExplorerVersion() {
1980
+ if (_ieVersion == -1) {
1981
+ var rv = -1; // Return value assumes failure.
1982
+ if (navigator.appName == 'Microsoft Internet Explorer')
1983
+ {
1984
+ var ua = navigator.userAgent;
1985
+ var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
1986
+ if (re.exec(ua) != null) {
1987
+ rv = parseFloat( RegExp.$1 );
1988
+ }
1989
+ }
1990
+
1991
+ _ieVersion = rv;
1992
+ }
1993
+
1994
+ return _ieVersion;
1995
+ };
1996
+
1997
+ /**
1998
+ * Test whether the current browser is Firefox
1999
+ * @returns {boolean} isFirefox
2000
+ */
2001
+ exports.isFirefox = function isFirefox () {
2002
+ return (navigator.userAgent.indexOf("Firefox") != -1);
2003
+ };
2004
+
2005
+ /**
2006
+ * cached internet explorer version
2007
+ * @type {Number}
2008
+ * @private
2009
+ */
2010
+ var _ieVersion = -1;
2011
+
2012
+ /**
2013
+ * Add and event listener. Works for all browsers
2014
+ * @param {Element} element An html element
2015
+ * @param {string} action The action, for example "click",
2016
+ * without the prefix "on"
2017
+ * @param {function} listener The callback function to be executed
2018
+ * @param {boolean} [useCapture] false by default
2019
+ * @return {function} the created event listener
2020
+ */
2021
+ exports.addEventListener = function addEventListener(element, action, listener, useCapture) {
2022
+ if (element.addEventListener) {
2023
+ if (useCapture === undefined)
2024
+ useCapture = false;
2025
+
2026
+ if (action === "mousewheel" && exports.isFirefox()) {
2027
+ action = "DOMMouseScroll"; // For Firefox
2028
+ }
2029
+
2030
+ element.addEventListener(action, listener, useCapture);
2031
+ return listener;
2032
+ } else if (element.attachEvent) {
2033
+ // Old IE browsers
2034
+ var f = function () {
2035
+ return listener.call(element, window.event);
2036
+ };
2037
+ element.attachEvent("on" + action, f);
2038
+ return f;
2039
+ }
2040
+ };
2041
+
2042
+ /**
2043
+ * Remove an event listener from an element
2044
+ * @param {Element} element An html dom element
2045
+ * @param {string} action The name of the event, for example "mousedown"
2046
+ * @param {function} listener The listener function
2047
+ * @param {boolean} [useCapture] false by default
2048
+ */
2049
+ exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) {
2050
+ if (element.removeEventListener) {
2051
+ if (useCapture === undefined)
2052
+ useCapture = false;
2053
+
2054
+ if (action === "mousewheel" && exports.isFirefox()) {
2055
+ action = "DOMMouseScroll"; // For Firefox
2056
+ }
2057
+
2058
+ element.removeEventListener(action, listener, useCapture);
2059
+ } else if (element.detachEvent) {
2060
+ // Old IE browsers
2061
+ element.detachEvent("on" + action, listener);
2062
+ }
2063
+ };
2064
+
2065
+
2066
+ /***/ },
2067
+ /* 4 */
2068
+ /***/ function(module, exports, __webpack_require__) {
2069
+
2070
+ /**
2071
+ * The highlighter can highlight/unhighlight a node, and
2072
+ * animate the visibility of a context menu.
2073
+ * @constructor Highlighter
2074
+ */
2075
+ function Highlighter () {
2076
+ this.locked = false;
2077
+ }
2078
+
2079
+ /**
2080
+ * Hightlight given node and its childs
2081
+ * @param {Node} node
2082
+ */
2083
+ Highlighter.prototype.highlight = function (node) {
2084
+ if (this.locked) {
2085
+ return;
2086
+ }
2087
+
2088
+ if (this.node != node) {
2089
+ // unhighlight current node
2090
+ if (this.node) {
2091
+ this.node.setHighlight(false);
2092
+ }
2093
+
2094
+ // highlight new node
2095
+ this.node = node;
2096
+ this.node.setHighlight(true);
2097
+ }
2098
+
2099
+ // cancel any current timeout
2100
+ this._cancelUnhighlight();
2101
+ };
2102
+
2103
+ /**
2104
+ * Unhighlight currently highlighted node.
2105
+ * Will be done after a delay
2106
+ */
2107
+ Highlighter.prototype.unhighlight = function () {
2108
+ if (this.locked) {
2109
+ return;
2110
+ }
2111
+
2112
+ var me = this;
2113
+ if (this.node) {
2114
+ this._cancelUnhighlight();
2115
+
2116
+ // do the unhighlighting after a small delay, to prevent re-highlighting
2117
+ // the same node when moving from the drag-icon to the contextmenu-icon
2118
+ // or vice versa.
2119
+ this.unhighlightTimer = setTimeout(function () {
2120
+ me.node.setHighlight(false);
2121
+ me.node = undefined;
2122
+ me.unhighlightTimer = undefined;
2123
+ }, 0);
2124
+ }
2125
+ };
2126
+
2127
+ /**
2128
+ * Cancel an unhighlight action (if before the timeout of the unhighlight action)
2129
+ * @private
2130
+ */
2131
+ Highlighter.prototype._cancelUnhighlight = function () {
2132
+ if (this.unhighlightTimer) {
2133
+ clearTimeout(this.unhighlightTimer);
2134
+ this.unhighlightTimer = undefined;
2135
+ }
2136
+ };
2137
+
2138
+ /**
2139
+ * Lock highlighting or unhighlighting nodes.
2140
+ * methods highlight and unhighlight do not work while locked.
2141
+ */
2142
+ Highlighter.prototype.lock = function () {
2143
+ this.locked = true;
2144
+ };
2145
+
2146
+ /**
2147
+ * Unlock highlighting or unhighlighting nodes
2148
+ */
2149
+ Highlighter.prototype.unlock = function () {
2150
+ this.locked = false;
2151
+ };
2152
+
2153
+ module.exports = Highlighter;
2154
+
2155
+
2156
+ /***/ },
2157
+ /* 5 */
2158
+ /***/ function(module, exports, __webpack_require__) {
2159
+
2160
+ var util = __webpack_require__(3);
2161
+
2162
+ /**
2163
+ * @constructor History
2164
+ * Store action history, enables undo and redo
2165
+ * @param {JSONEditor} editor
2166
+ */
2167
+ function History (editor) {
2168
+ this.editor = editor;
2169
+ this.clear();
2170
+
2171
+ // map with all supported actions
2172
+ this.actions = {
2173
+ 'editField': {
2174
+ 'undo': function (params) {
2175
+ params.node.updateField(params.oldValue);
2176
+ },
2177
+ 'redo': function (params) {
2178
+ params.node.updateField(params.newValue);
2179
+ }
2180
+ },
2181
+ 'editValue': {
2182
+ 'undo': function (params) {
2183
+ params.node.updateValue(params.oldValue);
2184
+ },
2185
+ 'redo': function (params) {
2186
+ params.node.updateValue(params.newValue);
2187
+ }
2188
+ },
2189
+ 'appendNode': {
2190
+ 'undo': function (params) {
2191
+ params.parent.removeChild(params.node);
2192
+ },
2193
+ 'redo': function (params) {
2194
+ params.parent.appendChild(params.node);
2195
+ }
2196
+ },
2197
+ 'insertBeforeNode': {
2198
+ 'undo': function (params) {
2199
+ params.parent.removeChild(params.node);
2200
+ },
2201
+ 'redo': function (params) {
2202
+ params.parent.insertBefore(params.node, params.beforeNode);
2203
+ }
2204
+ },
2205
+ 'insertAfterNode': {
2206
+ 'undo': function (params) {
2207
+ params.parent.removeChild(params.node);
2208
+ },
2209
+ 'redo': function (params) {
2210
+ params.parent.insertAfter(params.node, params.afterNode);
2211
+ }
2212
+ },
2213
+ 'removeNode': {
2214
+ 'undo': function (params) {
2215
+ var parent = params.parent;
2216
+ var beforeNode = parent.childs[params.index] || parent.append;
2217
+ parent.insertBefore(params.node, beforeNode);
2218
+ },
2219
+ 'redo': function (params) {
2220
+ params.parent.removeChild(params.node);
2221
+ }
2222
+ },
2223
+ 'duplicateNode': {
2224
+ 'undo': function (params) {
2225
+ params.parent.removeChild(params.clone);
2226
+ },
2227
+ 'redo': function (params) {
2228
+ params.parent.insertAfter(params.clone, params.node);
2229
+ }
2230
+ },
2231
+ 'changeType': {
2232
+ 'undo': function (params) {
2233
+ params.node.changeType(params.oldType);
2234
+ },
2235
+ 'redo': function (params) {
2236
+ params.node.changeType(params.newType);
2237
+ }
2238
+ },
2239
+ 'moveNode': {
2240
+ 'undo': function (params) {
2241
+ params.startParent.moveTo(params.node, params.startIndex);
2242
+ },
2243
+ 'redo': function (params) {
2244
+ params.endParent.moveTo(params.node, params.endIndex);
2245
+ }
2246
+ },
2247
+ 'sort': {
2248
+ 'undo': function (params) {
2249
+ var node = params.node;
2250
+ node.hideChilds();
2251
+ node.sort = params.oldSort;
2252
+ node.childs = params.oldChilds;
2253
+ node.showChilds();
2254
+ },
2255
+ 'redo': function (params) {
2256
+ var node = params.node;
2257
+ node.hideChilds();
2258
+ node.sort = params.newSort;
2259
+ node.childs = params.newChilds;
2260
+ node.showChilds();
2261
+ }
2262
+ }
2263
+
2264
+ // TODO: restore the original caret position and selection with each undo
2265
+ // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument"
2266
+ };
2267
+ }
2268
+
2269
+ /**
2270
+ * The method onChange is executed when the History is changed, and can
2271
+ * be overloaded.
2272
+ */
2273
+ History.prototype.onChange = function () {};
2274
+
2275
+ /**
2276
+ * Add a new action to the history
2277
+ * @param {String} action The executed action. Available actions: "editField",
2278
+ * "editValue", "changeType", "appendNode",
2279
+ * "removeNode", "duplicateNode", "moveNode"
2280
+ * @param {Object} params Object containing parameters describing the change.
2281
+ * The parameters in params depend on the action (for
2282
+ * example for "editValue" the Node, old value, and new
2283
+ * value are provided). params contains all information
2284
+ * needed to undo or redo the action.
2285
+ */
2286
+ History.prototype.add = function (action, params) {
2287
+ this.index++;
2288
+ this.history[this.index] = {
2289
+ 'action': action,
2290
+ 'params': params,
2291
+ 'timestamp': new Date()
2292
+ };
2293
+
2294
+ // remove redo actions which are invalid now
2295
+ if (this.index < this.history.length - 1) {
2296
+ this.history.splice(this.index + 1, this.history.length - this.index - 1);
2297
+ }
2298
+
2299
+ // fire onchange event
2300
+ this.onChange();
2301
+ };
2302
+
2303
+ /**
2304
+ * Clear history
2305
+ */
2306
+ History.prototype.clear = function () {
2307
+ this.history = [];
2308
+ this.index = -1;
2309
+
2310
+ // fire onchange event
2311
+ this.onChange();
2312
+ };
2313
+
2314
+ /**
2315
+ * Check if there is an action available for undo
2316
+ * @return {Boolean} canUndo
2317
+ */
2318
+ History.prototype.canUndo = function () {
2319
+ return (this.index >= 0);
2320
+ };
2321
+
2322
+ /**
2323
+ * Check if there is an action available for redo
2324
+ * @return {Boolean} canRedo
2325
+ */
2326
+ History.prototype.canRedo = function () {
2327
+ return (this.index < this.history.length - 1);
2328
+ };
2329
+
2330
+ /**
2331
+ * Undo the last action
2332
+ */
2333
+ History.prototype.undo = function () {
2334
+ if (this.canUndo()) {
2335
+ var obj = this.history[this.index];
2336
+ if (obj) {
2337
+ var action = this.actions[obj.action];
2338
+ if (action && action.undo) {
2339
+ action.undo(obj.params);
2340
+ if (obj.params.oldSelection) {
2341
+ this.editor.setSelection(obj.params.oldSelection);
2342
+ }
2343
+ }
2344
+ else {
2345
+ util.log('Error: unknown action "' + obj.action + '"');
2346
+ }
2347
+ }
2348
+ this.index--;
2349
+
2350
+ // fire onchange event
2351
+ this.onChange();
2352
+ }
2353
+ };
2354
+
2355
+ /**
2356
+ * Redo the last action
2357
+ */
2358
+ History.prototype.redo = function () {
2359
+ if (this.canRedo()) {
2360
+ this.index++;
2361
+
2362
+ var obj = this.history[this.index];
2363
+ if (obj) {
2364
+ var action = this.actions[obj.action];
2365
+ if (action && action.redo) {
2366
+ action.redo(obj.params);
2367
+ if (obj.params.newSelection) {
2368
+ this.editor.setSelection(obj.params.newSelection);
2369
+ }
2370
+ }
2371
+ else {
2372
+ util.log('Error: unknown action "' + obj.action + '"');
2373
+ }
2374
+ }
2375
+
2376
+ // fire onchange event
2377
+ this.onChange();
2378
+ }
2379
+ };
2380
+
2381
+ module.exports = History;
2382
+
2383
+
2384
+ /***/ },
2385
+ /* 6 */
2386
+ /***/ function(module, exports, __webpack_require__) {
2387
+
2388
+ /**
2389
+ * @constructor SearchBox
2390
+ * Create a search box in given HTML container
2391
+ * @param {JSONEditor} editor The JSON Editor to attach to
2392
+ * @param {Element} container HTML container element of where to
2393
+ * create the search box
2394
+ */
2395
+ function SearchBox (editor, container) {
2396
+ var searchBox = this;
2397
+
2398
+ this.editor = editor;
2399
+ this.timeout = undefined;
2400
+ this.delay = 200; // ms
2401
+ this.lastText = undefined;
2402
+
2403
+ this.dom = {};
2404
+ this.dom.container = container;
2405
+
2406
+ var table = document.createElement('table');
2407
+ this.dom.table = table;
2408
+ table.className = 'search';
2409
+ container.appendChild(table);
2410
+ var tbody = document.createElement('tbody');
2411
+ this.dom.tbody = tbody;
2412
+ table.appendChild(tbody);
2413
+ var tr = document.createElement('tr');
2414
+ tbody.appendChild(tr);
2415
+
2416
+ var td = document.createElement('td');
2417
+ tr.appendChild(td);
2418
+ var results = document.createElement('div');
2419
+ this.dom.results = results;
2420
+ results.className = 'results';
2421
+ td.appendChild(results);
2422
+
2423
+ td = document.createElement('td');
2424
+ tr.appendChild(td);
2425
+ var divInput = document.createElement('div');
2426
+ this.dom.input = divInput;
2427
+ divInput.className = 'frame';
2428
+ divInput.title = 'Search fields and values';
2429
+ td.appendChild(divInput);
2430
+
2431
+ // table to contain the text input and search button
2432
+ var tableInput = document.createElement('table');
2433
+ divInput.appendChild(tableInput);
2434
+ var tbodySearch = document.createElement('tbody');
2435
+ tableInput.appendChild(tbodySearch);
2436
+ tr = document.createElement('tr');
2437
+ tbodySearch.appendChild(tr);
2438
+
2439
+ var refreshSearch = document.createElement('button');
2440
+ refreshSearch.className = 'refresh';
2441
+ td = document.createElement('td');
2442
+ td.appendChild(refreshSearch);
2443
+ tr.appendChild(td);
2444
+
2445
+ var search = document.createElement('input');
2446
+ this.dom.search = search;
2447
+ search.oninput = function (event) {
2448
+ searchBox._onDelayedSearch(event);
2449
+ };
2450
+ search.onchange = function (event) { // For IE 9
2451
+ searchBox._onSearch(event);
2452
+ };
2453
+ search.onkeydown = function (event) {
2454
+ searchBox._onKeyDown(event);
2455
+ };
2456
+ search.onkeyup = function (event) {
2457
+ searchBox._onKeyUp(event);
2458
+ };
2459
+ refreshSearch.onclick = function (event) {
2460
+ search.select();
2461
+ };
2462
+
2463
+ // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819
2464
+ td = document.createElement('td');
2465
+ td.appendChild(search);
2466
+ tr.appendChild(td);
2467
+
2468
+ var searchNext = document.createElement('button');
2469
+ searchNext.title = 'Next result (Enter)';
2470
+ searchNext.className = 'next';
2471
+ searchNext.onclick = function () {
2472
+ searchBox.next();
2473
+ };
2474
+ td = document.createElement('td');
2475
+ td.appendChild(searchNext);
2476
+ tr.appendChild(td);
2477
+
2478
+ var searchPrevious = document.createElement('button');
2479
+ searchPrevious.title = 'Previous result (Shift+Enter)';
2480
+ searchPrevious.className = 'previous';
2481
+ searchPrevious.onclick = function () {
2482
+ searchBox.previous();
2483
+ };
2484
+ td = document.createElement('td');
2485
+ td.appendChild(searchPrevious);
2486
+ tr.appendChild(td);
2487
+ }
2488
+
2489
+ /**
2490
+ * Go to the next search result
2491
+ * @param {boolean} [focus] If true, focus will be set to the next result
2492
+ * focus is false by default.
2493
+ */
2494
+ SearchBox.prototype.next = function(focus) {
2495
+ if (this.results != undefined) {
2496
+ var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0;
2497
+ if (index > this.results.length - 1) {
2498
+ index = 0;
2499
+ }
2500
+ this._setActiveResult(index, focus);
2501
+ }
2502
+ };
2503
+
2504
+ /**
2505
+ * Go to the prevous search result
2506
+ * @param {boolean} [focus] If true, focus will be set to the next result
2507
+ * focus is false by default.
2508
+ */
2509
+ SearchBox.prototype.previous = function(focus) {
2510
+ if (this.results != undefined) {
2511
+ var max = this.results.length - 1;
2512
+ var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max;
2513
+ if (index < 0) {
2514
+ index = max;
2515
+ }
2516
+ this._setActiveResult(index, focus);
2517
+ }
2518
+ };
2519
+
2520
+ /**
2521
+ * Set new value for the current active result
2522
+ * @param {Number} index
2523
+ * @param {boolean} [focus] If true, focus will be set to the next result.
2524
+ * focus is false by default.
2525
+ * @private
2526
+ */
2527
+ SearchBox.prototype._setActiveResult = function(index, focus) {
2528
+ // de-activate current active result
2529
+ if (this.activeResult) {
2530
+ var prevNode = this.activeResult.node;
2531
+ var prevElem = this.activeResult.elem;
2532
+ if (prevElem == 'field') {
2533
+ delete prevNode.searchFieldActive;
2534
+ }
2535
+ else {
2536
+ delete prevNode.searchValueActive;
2537
+ }
2538
+ prevNode.updateDom();
2539
+ }
2540
+
2541
+ if (!this.results || !this.results[index]) {
2542
+ // out of range, set to undefined
2543
+ this.resultIndex = undefined;
2544
+ this.activeResult = undefined;
2545
+ return;
2546
+ }
2547
+
2548
+ this.resultIndex = index;
2549
+
2550
+ // set new node active
2551
+ var node = this.results[this.resultIndex].node;
2552
+ var elem = this.results[this.resultIndex].elem;
2553
+ if (elem == 'field') {
2554
+ node.searchFieldActive = true;
2555
+ }
2556
+ else {
2557
+ node.searchValueActive = true;
2558
+ }
2559
+ this.activeResult = this.results[this.resultIndex];
2560
+ node.updateDom();
2561
+
2562
+ // TODO: not so nice that the focus is only set after the animation is finished
2563
+ node.scrollTo(function () {
2564
+ if (focus) {
2565
+ node.focus(elem);
2566
+ }
2567
+ });
2568
+ };
2569
+
2570
+ /**
2571
+ * Cancel any running onDelayedSearch.
2572
+ * @private
2573
+ */
2574
+ SearchBox.prototype._clearDelay = function() {
2575
+ if (this.timeout != undefined) {
2576
+ clearTimeout(this.timeout);
2577
+ delete this.timeout;
2578
+ }
2579
+ };
2580
+
2581
+ /**
2582
+ * Start a timer to execute a search after a short delay.
2583
+ * Used for reducing the number of searches while typing.
2584
+ * @param {Event} event
2585
+ * @private
2586
+ */
2587
+ SearchBox.prototype._onDelayedSearch = function (event) {
2588
+ // execute the search after a short delay (reduces the number of
2589
+ // search actions while typing in the search text box)
2590
+ this._clearDelay();
2591
+ var searchBox = this;
2592
+ this.timeout = setTimeout(function (event) {
2593
+ searchBox._onSearch(event);
2594
+ },
2595
+ this.delay);
2596
+ };
2597
+
2598
+ /**
2599
+ * Handle onSearch event
2600
+ * @param {Event} event
2601
+ * @param {boolean} [forceSearch] If true, search will be executed again even
2602
+ * when the search text is not changed.
2603
+ * Default is false.
2604
+ * @private
2605
+ */
2606
+ SearchBox.prototype._onSearch = function (event, forceSearch) {
2607
+ this._clearDelay();
2608
+
2609
+ var value = this.dom.search.value;
2610
+ var text = (value.length > 0) ? value : undefined;
2611
+ if (text != this.lastText || forceSearch) {
2612
+ // only search again when changed
2613
+ this.lastText = text;
2614
+ this.results = this.editor.search(text);
2615
+ this._setActiveResult(undefined);
2616
+
2617
+ // display search results
2618
+ if (text != undefined) {
2619
+ var resultCount = this.results.length;
2620
+ switch (resultCount) {
2621
+ case 0: this.dom.results.innerHTML = 'no&nbsp;results'; break;
2622
+ case 1: this.dom.results.innerHTML = '1&nbsp;result'; break;
2623
+ default: this.dom.results.innerHTML = resultCount + '&nbsp;results'; break;
2624
+ }
2625
+ }
2626
+ else {
2627
+ this.dom.results.innerHTML = '';
2628
+ }
2629
+ }
2630
+ };
2631
+
2632
+ /**
2633
+ * Handle onKeyDown event in the input box
2634
+ * @param {Event} event
2635
+ * @private
2636
+ */
2637
+ SearchBox.prototype._onKeyDown = function (event) {
2638
+ var keynum = event.which;
2639
+ if (keynum == 27) { // ESC
2640
+ this.dom.search.value = ''; // clear search
2641
+ this._onSearch(event);
2642
+ event.preventDefault();
2643
+ event.stopPropagation();
2644
+ }
2645
+ else if (keynum == 13) { // Enter
2646
+ if (event.ctrlKey) {
2647
+ // force to search again
2648
+ this._onSearch(event, true);
2649
+ }
2650
+ else if (event.shiftKey) {
2651
+ // move to the previous search result
2652
+ this.previous();
2653
+ }
2654
+ else {
2655
+ // move to the next search result
2656
+ this.next();
2657
+ }
2658
+ event.preventDefault();
2659
+ event.stopPropagation();
2660
+ }
2661
+ };
2662
+
2663
+ /**
2664
+ * Handle onKeyUp event in the input box
2665
+ * @param {Event} event
2666
+ * @private
2667
+ */
2668
+ SearchBox.prototype._onKeyUp = function (event) {
2669
+ var keynum = event.keyCode;
2670
+ if (keynum != 27 && keynum != 13) { // !show and !Enter
2671
+ this._onDelayedSearch(event); // For IE 9
2672
+ }
2673
+ };
2674
+
2675
+ module.exports = SearchBox;
2676
+
2677
+
2678
+ /***/ },
2679
+ /* 7 */
2680
+ /***/ function(module, exports, __webpack_require__) {
2681
+
2682
+ var ContextMenu = __webpack_require__(10);
2683
+ var appendNodeFactory = __webpack_require__(11);
2684
+ var util = __webpack_require__(3);
2685
+
2686
+ /**
2687
+ * @constructor Node
2688
+ * Create a new Node
2689
+ * @param {TreeEditor} editor
2690
+ * @param {Object} [params] Can contain parameters:
2691
+ * {string} field
2692
+ * {boolean} fieldEditable
2693
+ * {*} value
2694
+ * {String} type Can have values 'auto', 'array',
2695
+ * 'object', or 'string'.
2696
+ */
2697
+ function Node (editor, params) {
2698
+ /** @type {TreeEditor} */
2699
+ this.editor = editor;
2700
+ this.dom = {};
2701
+ this.expanded = false;
2702
+
2703
+ if(params && (params instanceof Object)) {
2704
+ this.setField(params.field, params.fieldEditable);
2705
+ this.setValue(params.value, params.type);
2706
+ }
2707
+ else {
2708
+ this.setField('');
2709
+ this.setValue(null);
2710
+ }
2711
+ }
2712
+
2713
+ /**
2714
+ * Determine whether the field and/or value of this node are editable
2715
+ * @private
2716
+ */
2717
+ Node.prototype._updateEditability = function () {
2718
+ this.editable = {
2719
+ field: true,
2720
+ value: true
2721
+ };
2722
+
2723
+ if (this.editor) {
2724
+ this.editable.field = this.editor.options.mode === 'tree';
2725
+ this.editable.value = this.editor.options.mode !== 'view';
2726
+
2727
+ if (this.editor.options.mode === 'tree' && (typeof this.editor.options.editable === 'function')) {
2728
+ var editable = this.editor.options.editable({
2729
+ field: this.field,
2730
+ value: this.value,
2731
+ path: this.path()
2732
+ });
2733
+
2734
+ if (typeof editable === 'boolean') {
2735
+ this.editable.field = editable;
2736
+ this.editable.value = editable;
2737
+ }
2738
+ else {
2739
+ if (typeof editable.field === 'boolean') this.editable.field = editable.field;
2740
+ if (typeof editable.value === 'boolean') this.editable.value = editable.value;
2741
+ }
2742
+ }
2743
+ }
2744
+ };
2745
+
2746
+ /**
2747
+ * Get the path of this node
2748
+ * @return {String[]} Array containing the path to this node
2749
+ */
2750
+ Node.prototype.path = function () {
2751
+ var node = this;
2752
+ var path = [];
2753
+ while (node) {
2754
+ var field = node.field != undefined ? node.field : node.index;
2755
+ if (field !== undefined) {
2756
+ path.unshift(field);
2757
+ }
2758
+ node = node.parent;
2759
+ }
2760
+ return path;
2761
+ };
2762
+
2763
+ /**
2764
+ * Set parent node
2765
+ * @param {Node} parent
2766
+ */
2767
+ Node.prototype.setParent = function(parent) {
2768
+ this.parent = parent;
2769
+ };
2770
+
2771
+ /**
2772
+ * Set field
2773
+ * @param {String} field
2774
+ * @param {boolean} [fieldEditable]
2775
+ */
2776
+ Node.prototype.setField = function(field, fieldEditable) {
2777
+ this.field = field;
2778
+ this.fieldEditable = (fieldEditable === true);
2779
+ };
2780
+
2781
+ /**
2782
+ * Get field
2783
+ * @return {String}
2784
+ */
2785
+ Node.prototype.getField = function() {
2786
+ if (this.field === undefined) {
2787
+ this._getDomField();
2788
+ }
2789
+
2790
+ return this.field;
2791
+ };
2792
+
2793
+ /**
2794
+ * Set value. Value is a JSON structure or an element String, Boolean, etc.
2795
+ * @param {*} value
2796
+ * @param {String} [type] Specify the type of the value. Can be 'auto',
2797
+ * 'array', 'object', or 'string'
2798
+ */
2799
+ Node.prototype.setValue = function(value, type) {
2800
+ var childValue, child;
2801
+
2802
+ // first clear all current childs (if any)
2803
+ var childs = this.childs;
2804
+ if (childs) {
2805
+ while (childs.length) {
2806
+ this.removeChild(childs[0]);
2807
+ }
2808
+ }
2809
+
2810
+ // TODO: remove the DOM of this Node
2811
+
2812
+ this.type = this._getType(value);
2813
+
2814
+ // check if type corresponds with the provided type
2815
+ if (type && type != this.type) {
2816
+ if (type == 'string' && this.type == 'auto') {
2817
+ this.type = type;
2818
+ }
2819
+ else {
2820
+ throw new Error('Type mismatch: ' +
2821
+ 'cannot cast value of type "' + this.type +
2822
+ ' to the specified type "' + type + '"');
2823
+ }
2824
+ }
2825
+
2826
+ if (this.type == 'array') {
2827
+ // array
2828
+ this.childs = [];
2829
+ for (var i = 0, iMax = value.length; i < iMax; i++) {
2830
+ childValue = value[i];
2831
+ if (childValue !== undefined && !(childValue instanceof Function)) {
2832
+ // ignore undefined and functions
2833
+ child = new Node(this.editor, {
2834
+ value: childValue
2835
+ });
2836
+ this.appendChild(child);
2837
+ }
2838
+ }
2839
+ this.value = '';
2840
+ }
2841
+ else if (this.type == 'object') {
2842
+ // object
2843
+ this.childs = [];
2844
+ for (var childField in value) {
2845
+ if (value.hasOwnProperty(childField)) {
2846
+ childValue = value[childField];
2847
+ if (childValue !== undefined && !(childValue instanceof Function)) {
2848
+ // ignore undefined and functions
2849
+ child = new Node(this.editor, {
2850
+ field: childField,
2851
+ value: childValue
2852
+ });
2853
+ this.appendChild(child);
2854
+ }
2855
+ }
2856
+ }
2857
+ this.value = '';
2858
+ }
2859
+ else {
2860
+ // value
2861
+ this.childs = undefined;
2862
+ this.value = value;
2863
+ /* TODO
2864
+ if (typeof(value) == 'string') {
2865
+ var escValue = JSON.stringify(value);
2866
+ this.value = escValue.substring(1, escValue.length - 1);
2867
+ util.log('check', value, this.value);
2868
+ }
2869
+ else {
2870
+ this.value = value;
2871
+ }
2872
+ */
2873
+ }
2874
+ };
2875
+
2876
+ /**
2877
+ * Get value. Value is a JSON structure
2878
+ * @return {*} value
2879
+ */
2880
+ Node.prototype.getValue = function() {
2881
+ //var childs, i, iMax;
2882
+
2883
+ if (this.type == 'array') {
2884
+ var arr = [];
2885
+ this.childs.forEach (function (child) {
2886
+ arr.push(child.getValue());
2887
+ });
2888
+ return arr;
2889
+ }
2890
+ else if (this.type == 'object') {
2891
+ var obj = {};
2892
+ this.childs.forEach (function (child) {
2893
+ obj[child.getField()] = child.getValue();
2894
+ });
2895
+ return obj;
2896
+ }
2897
+ else {
2898
+ if (this.value === undefined) {
2899
+ this._getDomValue();
2900
+ }
2901
+
2902
+ return this.value;
2903
+ }
2904
+ };
2905
+
2906
+ /**
2907
+ * Get the nesting level of this node
2908
+ * @return {Number} level
2909
+ */
2910
+ Node.prototype.getLevel = function() {
2911
+ return (this.parent ? this.parent.getLevel() + 1 : 0);
2912
+ };
2913
+
2914
+ /**
2915
+ * Create a clone of a node
2916
+ * The complete state of a clone is copied, including whether it is expanded or
2917
+ * not. The DOM elements are not cloned.
2918
+ * @return {Node} clone
2919
+ */
2920
+ Node.prototype.clone = function() {
2921
+ var clone = new Node(this.editor);
2922
+ clone.type = this.type;
2923
+ clone.field = this.field;
2924
+ clone.fieldInnerText = this.fieldInnerText;
2925
+ clone.fieldEditable = this.fieldEditable;
2926
+ clone.value = this.value;
2927
+ clone.valueInnerText = this.valueInnerText;
2928
+ clone.expanded = this.expanded;
2929
+
2930
+ if (this.childs) {
2931
+ // an object or array
2932
+ var cloneChilds = [];
2933
+ this.childs.forEach(function (child) {
2934
+ var childClone = child.clone();
2935
+ childClone.setParent(clone);
2936
+ cloneChilds.push(childClone);
2937
+ });
2938
+ clone.childs = cloneChilds;
2939
+ }
2940
+ else {
2941
+ // a value
2942
+ clone.childs = undefined;
2943
+ }
2944
+
2945
+ return clone;
2946
+ };
2947
+
2948
+ /**
2949
+ * Expand this node and optionally its childs.
2950
+ * @param {boolean} [recurse] Optional recursion, true by default. When
2951
+ * true, all childs will be expanded recursively
2952
+ */
2953
+ Node.prototype.expand = function(recurse) {
2954
+ if (!this.childs) {
2955
+ return;
2956
+ }
2957
+
2958
+ // set this node expanded
2959
+ this.expanded = true;
2960
+ if (this.dom.expand) {
2961
+ this.dom.expand.className = 'expanded';
2962
+ }
2963
+
2964
+ this.showChilds();
2965
+
2966
+ if (recurse !== false) {
2967
+ this.childs.forEach(function (child) {
2968
+ child.expand(recurse);
2969
+ });
2970
+ }
2971
+ };
2972
+
2973
+ /**
2974
+ * Collapse this node and optionally its childs.
2975
+ * @param {boolean} [recurse] Optional recursion, true by default. When
2976
+ * true, all childs will be collapsed recursively
2977
+ */
2978
+ Node.prototype.collapse = function(recurse) {
2979
+ if (!this.childs) {
2980
+ return;
2981
+ }
2982
+
2983
+ this.hideChilds();
2984
+
2985
+ // collapse childs in case of recurse
2986
+ if (recurse !== false) {
2987
+ this.childs.forEach(function (child) {
2988
+ child.collapse(recurse);
2989
+ });
2990
+
2991
+ }
2992
+
2993
+ // make this node collapsed
2994
+ if (this.dom.expand) {
2995
+ this.dom.expand.className = 'collapsed';
2996
+ }
2997
+ this.expanded = false;
2998
+ };
2999
+
3000
+ /**
3001
+ * Recursively show all childs when they are expanded
3002
+ */
3003
+ Node.prototype.showChilds = function() {
3004
+ var childs = this.childs;
3005
+ if (!childs) {
3006
+ return;
3007
+ }
3008
+ if (!this.expanded) {
3009
+ return;
3010
+ }
3011
+
3012
+ var tr = this.dom.tr;
3013
+ var table = tr ? tr.parentNode : undefined;
3014
+ if (table) {
3015
+ // show row with append button
3016
+ var append = this.getAppend();
3017
+ var nextTr = tr.nextSibling;
3018
+ if (nextTr) {
3019
+ table.insertBefore(append, nextTr);
3020
+ }
3021
+ else {
3022
+ table.appendChild(append);
3023
+ }
3024
+
3025
+ // show childs
3026
+ this.childs.forEach(function (child) {
3027
+ table.insertBefore(child.getDom(), append);
3028
+ child.showChilds();
3029
+ });
3030
+ }
3031
+ };
3032
+
3033
+ /**
3034
+ * Hide the node with all its childs
3035
+ */
3036
+ Node.prototype.hide = function() {
3037
+ var tr = this.dom.tr;
3038
+ var table = tr ? tr.parentNode : undefined;
3039
+ if (table) {
3040
+ table.removeChild(tr);
3041
+ }
3042
+ this.hideChilds();
3043
+ };
3044
+
3045
+
3046
+ /**
3047
+ * Recursively hide all childs
3048
+ */
3049
+ Node.prototype.hideChilds = function() {
3050
+ var childs = this.childs;
3051
+ if (!childs) {
3052
+ return;
3053
+ }
3054
+ if (!this.expanded) {
3055
+ return;
3056
+ }
3057
+
3058
+ // hide append row
3059
+ var append = this.getAppend();
3060
+ if (append.parentNode) {
3061
+ append.parentNode.removeChild(append);
3062
+ }
3063
+
3064
+ // hide childs
3065
+ this.childs.forEach(function (child) {
3066
+ child.hide();
3067
+ });
3068
+ };
3069
+
3070
+
3071
+ /**
3072
+ * Add a new child to the node.
3073
+ * Only applicable when Node value is of type array or object
3074
+ * @param {Node} node
3075
+ */
3076
+ Node.prototype.appendChild = function(node) {
3077
+ if (this._hasChilds()) {
3078
+ // adjust the link to the parent
3079
+ node.setParent(this);
3080
+ node.fieldEditable = (this.type == 'object');
3081
+ if (this.type == 'array') {
3082
+ node.index = this.childs.length;
3083
+ }
3084
+ this.childs.push(node);
3085
+
3086
+ if (this.expanded) {
3087
+ // insert into the DOM, before the appendRow
3088
+ var newTr = node.getDom();
3089
+ var appendTr = this.getAppend();
3090
+ var table = appendTr ? appendTr.parentNode : undefined;
3091
+ if (appendTr && table) {
3092
+ table.insertBefore(newTr, appendTr);
3093
+ }
3094
+
3095
+ node.showChilds();
3096
+ }
3097
+
3098
+ this.updateDom({'updateIndexes': true});
3099
+ node.updateDom({'recurse': true});
3100
+ }
3101
+ };
3102
+
3103
+
3104
+ /**
3105
+ * Move a node from its current parent to this node
3106
+ * Only applicable when Node value is of type array or object
3107
+ * @param {Node} node
3108
+ * @param {Node} beforeNode
3109
+ */
3110
+ Node.prototype.moveBefore = function(node, beforeNode) {
3111
+ if (this._hasChilds()) {
3112
+ // create a temporary row, to prevent the scroll position from jumping
3113
+ // when removing the node
3114
+ var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined;
3115
+ if (tbody) {
3116
+ var trTemp = document.createElement('tr');
3117
+ trTemp.style.height = tbody.clientHeight + 'px';
3118
+ tbody.appendChild(trTemp);
3119
+ }
3120
+
3121
+ if (node.parent) {
3122
+ node.parent.removeChild(node);
3123
+ }
3124
+
3125
+ if (beforeNode instanceof AppendNode) {
3126
+ this.appendChild(node);
3127
+ }
3128
+ else {
3129
+ this.insertBefore(node, beforeNode);
3130
+ }
3131
+
3132
+ if (tbody) {
3133
+ tbody.removeChild(trTemp);
3134
+ }
3135
+ }
3136
+ };
3137
+
3138
+ /**
3139
+ * Move a node from its current parent to this node
3140
+ * Only applicable when Node value is of type array or object.
3141
+ * If index is out of range, the node will be appended to the end
3142
+ * @param {Node} node
3143
+ * @param {Number} index
3144
+ */
3145
+ Node.prototype.moveTo = function (node, index) {
3146
+ if (node.parent == this) {
3147
+ // same parent
3148
+ var currentIndex = this.childs.indexOf(node);
3149
+ if (currentIndex < index) {
3150
+ // compensate the index for removal of the node itself
3151
+ index++;
3152
+ }
3153
+ }
3154
+
3155
+ var beforeNode = this.childs[index] || this.append;
3156
+ this.moveBefore(node, beforeNode);
3157
+ };
3158
+
3159
+ /**
3160
+ * Insert a new child before a given node
3161
+ * Only applicable when Node value is of type array or object
3162
+ * @param {Node} node
3163
+ * @param {Node} beforeNode
3164
+ */
3165
+ Node.prototype.insertBefore = function(node, beforeNode) {
3166
+ if (this._hasChilds()) {
3167
+ if (beforeNode == this.append) {
3168
+ // append to the child nodes
3169
+
3170
+ // adjust the link to the parent
3171
+ node.setParent(this);
3172
+ node.fieldEditable = (this.type == 'object');
3173
+ this.childs.push(node);
3174
+ }
3175
+ else {
3176
+ // insert before a child node
3177
+ var index = this.childs.indexOf(beforeNode);
3178
+ if (index == -1) {
3179
+ throw new Error('Node not found');
3180
+ }
3181
+
3182
+ // adjust the link to the parent
3183
+ node.setParent(this);
3184
+ node.fieldEditable = (this.type == 'object');
3185
+ this.childs.splice(index, 0, node);
3186
+ }
3187
+
3188
+ if (this.expanded) {
3189
+ // insert into the DOM
3190
+ var newTr = node.getDom();
3191
+ var nextTr = beforeNode.getDom();
3192
+ var table = nextTr ? nextTr.parentNode : undefined;
3193
+ if (nextTr && table) {
3194
+ table.insertBefore(newTr, nextTr);
3195
+ }
3196
+
3197
+ node.showChilds();
3198
+ }
3199
+
3200
+ this.updateDom({'updateIndexes': true});
3201
+ node.updateDom({'recurse': true});
3202
+ }
3203
+ };
3204
+
3205
+ /**
3206
+ * Insert a new child before a given node
3207
+ * Only applicable when Node value is of type array or object
3208
+ * @param {Node} node
3209
+ * @param {Node} afterNode
3210
+ */
3211
+ Node.prototype.insertAfter = function(node, afterNode) {
3212
+ if (this._hasChilds()) {
3213
+ var index = this.childs.indexOf(afterNode);
3214
+ var beforeNode = this.childs[index + 1];
3215
+ if (beforeNode) {
3216
+ this.insertBefore(node, beforeNode);
3217
+ }
3218
+ else {
3219
+ this.appendChild(node);
3220
+ }
3221
+ }
3222
+ };
3223
+
3224
+ /**
3225
+ * Search in this node
3226
+ * The node will be expanded when the text is found one of its childs, else
3227
+ * it will be collapsed. Searches are case insensitive.
3228
+ * @param {String} text
3229
+ * @return {Node[]} results Array with nodes containing the search text
3230
+ */
3231
+ Node.prototype.search = function(text) {
3232
+ var results = [];
3233
+ var index;
3234
+ var search = text ? text.toLowerCase() : undefined;
3235
+
3236
+ // delete old search data
3237
+ delete this.searchField;
3238
+ delete this.searchValue;
3239
+
3240
+ // search in field
3241
+ if (this.field != undefined) {
3242
+ var field = String(this.field).toLowerCase();
3243
+ index = field.indexOf(search);
3244
+ if (index != -1) {
3245
+ this.searchField = true;
3246
+ results.push({
3247
+ 'node': this,
3248
+ 'elem': 'field'
3249
+ });
3250
+ }
3251
+
3252
+ // update dom
3253
+ this._updateDomField();
3254
+ }
3255
+
3256
+ // search in value
3257
+ if (this._hasChilds()) {
3258
+ // array, object
3259
+
3260
+ // search the nodes childs
3261
+ if (this.childs) {
3262
+ var childResults = [];
3263
+ this.childs.forEach(function (child) {
3264
+ childResults = childResults.concat(child.search(text));
3265
+ });
3266
+ results = results.concat(childResults);
3267
+ }
3268
+
3269
+ // update dom
3270
+ if (search != undefined) {
3271
+ var recurse = false;
3272
+ if (childResults.length == 0) {
3273
+ this.collapse(recurse);
3274
+ }
3275
+ else {
3276
+ this.expand(recurse);
3277
+ }
3278
+ }
3279
+ }
3280
+ else {
3281
+ // string, auto
3282
+ if (this.value != undefined ) {
3283
+ var value = String(this.value).toLowerCase();
3284
+ index = value.indexOf(search);
3285
+ if (index != -1) {
3286
+ this.searchValue = true;
3287
+ results.push({
3288
+ 'node': this,
3289
+ 'elem': 'value'
3290
+ });
3291
+ }
3292
+ }
3293
+
3294
+ // update dom
3295
+ this._updateDomValue();
3296
+ }
3297
+
3298
+ return results;
3299
+ };
3300
+
3301
+ /**
3302
+ * Move the scroll position such that this node is in the visible area.
3303
+ * The node will not get the focus
3304
+ * @param {function(boolean)} [callback]
3305
+ */
3306
+ Node.prototype.scrollTo = function(callback) {
3307
+ if (!this.dom.tr || !this.dom.tr.parentNode) {
3308
+ // if the node is not visible, expand its parents
3309
+ var parent = this.parent;
3310
+ var recurse = false;
3311
+ while (parent) {
3312
+ parent.expand(recurse);
3313
+ parent = parent.parent;
3314
+ }
3315
+ }
3316
+
3317
+ if (this.dom.tr && this.dom.tr.parentNode) {
3318
+ this.editor.scrollTo(this.dom.tr.offsetTop, callback);
3319
+ }
3320
+ };
3321
+
3322
+
3323
+ // stores the element name currently having the focus
3324
+ Node.focusElement = undefined;
3325
+
3326
+ /**
3327
+ * Set focus to this node
3328
+ * @param {String} [elementName] The field name of the element to get the
3329
+ * focus available values: 'drag', 'menu',
3330
+ * 'expand', 'field', 'value' (default)
3331
+ */
3332
+ Node.prototype.focus = function(elementName) {
3333
+ Node.focusElement = elementName;
3334
+
3335
+ if (this.dom.tr && this.dom.tr.parentNode) {
3336
+ var dom = this.dom;
3337
+
3338
+ switch (elementName) {
3339
+ case 'drag':
3340
+ if (dom.drag) {
3341
+ dom.drag.focus();
3342
+ }
3343
+ else {
3344
+ dom.menu.focus();
3345
+ }
3346
+ break;
3347
+
3348
+ case 'menu':
3349
+ dom.menu.focus();
3350
+ break;
3351
+
3352
+ case 'expand':
3353
+ if (this._hasChilds()) {
3354
+ dom.expand.focus();
3355
+ }
3356
+ else if (dom.field && this.fieldEditable) {
3357
+ dom.field.focus();
3358
+ util.selectContentEditable(dom.field);
3359
+ }
3360
+ else if (dom.value && !this._hasChilds()) {
3361
+ dom.value.focus();
3362
+ util.selectContentEditable(dom.value);
3363
+ }
3364
+ else {
3365
+ dom.menu.focus();
3366
+ }
3367
+ break;
3368
+
3369
+ case 'field':
3370
+ if (dom.field && this.fieldEditable) {
3371
+ dom.field.focus();
3372
+ util.selectContentEditable(dom.field);
3373
+ }
3374
+ else if (dom.value && !this._hasChilds()) {
3375
+ dom.value.focus();
3376
+ util.selectContentEditable(dom.value);
3377
+ }
3378
+ else if (this._hasChilds()) {
3379
+ dom.expand.focus();
3380
+ }
3381
+ else {
3382
+ dom.menu.focus();
3383
+ }
3384
+ break;
3385
+
3386
+ case 'value':
3387
+ default:
3388
+ if (dom.value && !this._hasChilds()) {
3389
+ dom.value.focus();
3390
+ util.selectContentEditable(dom.value);
3391
+ }
3392
+ else if (dom.field && this.fieldEditable) {
3393
+ dom.field.focus();
3394
+ util.selectContentEditable(dom.field);
3395
+ }
3396
+ else if (this._hasChilds()) {
3397
+ dom.expand.focus();
3398
+ }
3399
+ else {
3400
+ dom.menu.focus();
3401
+ }
3402
+ break;
3403
+ }
3404
+ }
3405
+ };
3406
+
3407
+ /**
3408
+ * Select all text in an editable div after a delay of 0 ms
3409
+ * @param {Element} editableDiv
3410
+ */
3411
+ Node.select = function(editableDiv) {
3412
+ setTimeout(function () {
3413
+ util.selectContentEditable(editableDiv);
3414
+ }, 0);
3415
+ };
3416
+
3417
+ /**
3418
+ * Update the values from the DOM field and value of this node
3419
+ */
3420
+ Node.prototype.blur = function() {
3421
+ // retrieve the actual field and value from the DOM.
3422
+ this._getDomValue(false);
3423
+ this._getDomField(false);
3424
+ };
3425
+
3426
+ /**
3427
+ * Duplicate given child node
3428
+ * new structure will be added right before the cloned node
3429
+ * @param {Node} node the childNode to be duplicated
3430
+ * @return {Node} clone the clone of the node
3431
+ * @private
3432
+ */
3433
+ Node.prototype._duplicate = function(node) {
3434
+ var clone = node.clone();
3435
+
3436
+ /* TODO: adjust the field name (to prevent equal field names)
3437
+ if (this.type == 'object') {
3438
+ }
3439
+ */
3440
+
3441
+ this.insertAfter(clone, node);
3442
+
3443
+ return clone;
3444
+ };
3445
+
3446
+ /**
3447
+ * Check if given node is a child. The method will check recursively to find
3448
+ * this node.
3449
+ * @param {Node} node
3450
+ * @return {boolean} containsNode
3451
+ */
3452
+ Node.prototype.containsNode = function(node) {
3453
+ if (this == node) {
3454
+ return true;
3455
+ }
3456
+
3457
+ var childs = this.childs;
3458
+ if (childs) {
3459
+ // TODO: use the js5 Array.some() here?
3460
+ for (var i = 0, iMax = childs.length; i < iMax; i++) {
3461
+ if (childs[i].containsNode(node)) {
3462
+ return true;
3463
+ }
3464
+ }
3465
+ }
3466
+
3467
+ return false;
3468
+ };
3469
+
3470
+ /**
3471
+ * Move given node into this node
3472
+ * @param {Node} node the childNode to be moved
3473
+ * @param {Node} beforeNode node will be inserted before given
3474
+ * node. If no beforeNode is given,
3475
+ * the node is appended at the end
3476
+ * @private
3477
+ */
3478
+ Node.prototype._move = function(node, beforeNode) {
3479
+ if (node == beforeNode) {
3480
+ // nothing to do...
3481
+ return;
3482
+ }
3483
+
3484
+ // check if this node is not a child of the node to be moved here
3485
+ if (node.containsNode(this)) {
3486
+ throw new Error('Cannot move a field into a child of itself');
3487
+ }
3488
+
3489
+ // remove the original node
3490
+ if (node.parent) {
3491
+ node.parent.removeChild(node);
3492
+ }
3493
+
3494
+ // create a clone of the node
3495
+ var clone = node.clone();
3496
+ node.clearDom();
3497
+
3498
+ // insert or append the node
3499
+ if (beforeNode) {
3500
+ this.insertBefore(clone, beforeNode);
3501
+ }
3502
+ else {
3503
+ this.appendChild(clone);
3504
+ }
3505
+
3506
+ /* TODO: adjust the field name (to prevent equal field names)
3507
+ if (this.type == 'object') {
3508
+ }
3509
+ */
3510
+ };
3511
+
3512
+ /**
3513
+ * Remove a child from the node.
3514
+ * Only applicable when Node value is of type array or object
3515
+ * @param {Node} node The child node to be removed;
3516
+ * @return {Node | undefined} node The removed node on success,
3517
+ * else undefined
3518
+ */
3519
+ Node.prototype.removeChild = function(node) {
3520
+ if (this.childs) {
3521
+ var index = this.childs.indexOf(node);
3522
+
3523
+ if (index != -1) {
3524
+ node.hide();
3525
+
3526
+ // delete old search results
3527
+ delete node.searchField;
3528
+ delete node.searchValue;
3529
+
3530
+ var removedNode = this.childs.splice(index, 1)[0];
3531
+
3532
+ this.updateDom({'updateIndexes': true});
3533
+
3534
+ return removedNode;
3535
+ }
3536
+ }
3537
+
3538
+ return undefined;
3539
+ };
3540
+
3541
+ /**
3542
+ * Remove a child node node from this node
3543
+ * This method is equal to Node.removeChild, except that _remove firex an
3544
+ * onChange event.
3545
+ * @param {Node} node
3546
+ * @private
3547
+ */
3548
+ Node.prototype._remove = function (node) {
3549
+ this.removeChild(node);
3550
+ };
3551
+
3552
+ /**
3553
+ * Change the type of the value of this Node
3554
+ * @param {String} newType
3555
+ */
3556
+ Node.prototype.changeType = function (newType) {
3557
+ var oldType = this.type;
3558
+
3559
+ if (oldType == newType) {
3560
+ // type is not changed
3561
+ return;
3562
+ }
3563
+
3564
+ if ((newType == 'string' || newType == 'auto') &&
3565
+ (oldType == 'string' || oldType == 'auto')) {
3566
+ // this is an easy change
3567
+ this.type = newType;
3568
+ }
3569
+ else {
3570
+ // change from array to object, or from string/auto to object/array
3571
+ var table = this.dom.tr ? this.dom.tr.parentNode : undefined;
3572
+ var lastTr;
3573
+ if (this.expanded) {
3574
+ lastTr = this.getAppend();
3575
+ }
3576
+ else {
3577
+ lastTr = this.getDom();
3578
+ }
3579
+ var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined;
3580
+
3581
+ // hide current field and all its childs
3582
+ this.hide();
3583
+ this.clearDom();
3584
+
3585
+ // adjust the field and the value
3586
+ this.type = newType;
3587
+
3588
+ // adjust childs
3589
+ if (newType == 'object') {
3590
+ if (!this.childs) {
3591
+ this.childs = [];
3592
+ }
3593
+
3594
+ this.childs.forEach(function (child, index) {
3595
+ child.clearDom();
3596
+ delete child.index;
3597
+ child.fieldEditable = true;
3598
+ if (child.field == undefined) {
3599
+ child.field = '';
3600
+ }
3601
+ });
3602
+
3603
+ if (oldType == 'string' || oldType == 'auto') {
3604
+ this.expanded = true;
3605
+ }
3606
+ }
3607
+ else if (newType == 'array') {
3608
+ if (!this.childs) {
3609
+ this.childs = [];
3610
+ }
3611
+
3612
+ this.childs.forEach(function (child, index) {
3613
+ child.clearDom();
3614
+ child.fieldEditable = false;
3615
+ child.index = index;
3616
+ });
3617
+
3618
+ if (oldType == 'string' || oldType == 'auto') {
3619
+ this.expanded = true;
3620
+ }
3621
+ }
3622
+ else {
3623
+ this.expanded = false;
3624
+ }
3625
+
3626
+ // create new DOM
3627
+ if (table) {
3628
+ if (nextTr) {
3629
+ table.insertBefore(this.getDom(), nextTr);
3630
+ }
3631
+ else {
3632
+ table.appendChild(this.getDom());
3633
+ }
3634
+ }
3635
+ this.showChilds();
3636
+ }
3637
+
3638
+ if (newType == 'auto' || newType == 'string') {
3639
+ // cast value to the correct type
3640
+ if (newType == 'string') {
3641
+ this.value = String(this.value);
3642
+ }
3643
+ else {
3644
+ this.value = this._stringCast(String(this.value));
3645
+ }
3646
+
3647
+ this.focus();
3648
+ }
3649
+
3650
+ this.updateDom({'updateIndexes': true});
3651
+ };
3652
+
3653
+ /**
3654
+ * Retrieve value from DOM
3655
+ * @param {boolean} [silent] If true (default), no errors will be thrown in
3656
+ * case of invalid data
3657
+ * @private
3658
+ */
3659
+ Node.prototype._getDomValue = function(silent) {
3660
+ if (this.dom.value && this.type != 'array' && this.type != 'object') {
3661
+ this.valueInnerText = util.getInnerText(this.dom.value);
3662
+ }
3663
+
3664
+ if (this.valueInnerText != undefined) {
3665
+ try {
3666
+ // retrieve the value
3667
+ var value;
3668
+ if (this.type == 'string') {
3669
+ value = this._unescapeHTML(this.valueInnerText);
3670
+ }
3671
+ else {
3672
+ var str = this._unescapeHTML(this.valueInnerText);
3673
+ value = this._stringCast(str);
3674
+ }
3675
+ if (value !== this.value) {
3676
+ var oldValue = this.value;
3677
+ this.value = value;
3678
+ this.editor._onAction('editValue', {
3679
+ 'node': this,
3680
+ 'oldValue': oldValue,
3681
+ 'newValue': value,
3682
+ 'oldSelection': this.editor.selection,
3683
+ 'newSelection': this.editor.getSelection()
3684
+ });
3685
+ }
3686
+ }
3687
+ catch (err) {
3688
+ this.value = undefined;
3689
+ // TODO: sent an action with the new, invalid value?
3690
+ if (silent !== true) {
3691
+ throw err;
3692
+ }
3693
+ }
3694
+ }
3695
+ };
3696
+
3697
+ /**
3698
+ * Update dom value:
3699
+ * - the text color of the value, depending on the type of the value
3700
+ * - the height of the field, depending on the width
3701
+ * - background color in case it is empty
3702
+ * @private
3703
+ */
3704
+ Node.prototype._updateDomValue = function () {
3705
+ var domValue = this.dom.value;
3706
+ if (domValue) {
3707
+ // set text color depending on value type
3708
+ // TODO: put colors in css
3709
+ var v = this.value;
3710
+ var t = (this.type == 'auto') ? util.type(v) : this.type;
3711
+ var isUrl = (t == 'string' && util.isUrl(v));
3712
+ var color = '';
3713
+ if (isUrl && !this.editable.value) { // TODO: when to apply this?
3714
+ color = '';
3715
+ }
3716
+ else if (t == 'string') {
3717
+ color = 'green';
3718
+ }
3719
+ else if (t == 'number') {
3720
+ color = 'red';
3721
+ }
3722
+ else if (t == 'boolean') {
3723
+ color = 'darkorange';
3724
+ }
3725
+ else if (this._hasChilds()) {
3726
+ color = '';
3727
+ }
3728
+ else if (v === null) {
3729
+ color = '#004ED0'; // blue
3730
+ }
3731
+ else {
3732
+ // invalid value
3733
+ color = 'black';
3734
+ }
3735
+ domValue.style.color = color;
3736
+
3737
+ // make background color light-gray when empty
3738
+ var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object');
3739
+ if (isEmpty) {
3740
+ util.addClassName(domValue, 'empty');
3741
+ }
3742
+ else {
3743
+ util.removeClassName(domValue, 'empty');
3744
+ }
3745
+
3746
+ // underline url
3747
+ if (isUrl) {
3748
+ util.addClassName(domValue, 'url');
3749
+ }
3750
+ else {
3751
+ util.removeClassName(domValue, 'url');
3752
+ }
3753
+
3754
+ // update title
3755
+ if (t == 'array' || t == 'object') {
3756
+ var count = this.childs ? this.childs.length : 0;
3757
+ domValue.title = this.type + ' containing ' + count + ' items';
3758
+ }
3759
+ else if (t == 'string' && util.isUrl(v)) {
3760
+ if (this.editable.value) {
3761
+ domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window';
3762
+ }
3763
+ }
3764
+ else {
3765
+ domValue.title = '';
3766
+ }
3767
+
3768
+ // highlight when there is a search result
3769
+ if (this.searchValueActive) {
3770
+ util.addClassName(domValue, 'highlight-active');
3771
+ }
3772
+ else {
3773
+ util.removeClassName(domValue, 'highlight-active');
3774
+ }
3775
+ if (this.searchValue) {
3776
+ util.addClassName(domValue, 'highlight');
3777
+ }
3778
+ else {
3779
+ util.removeClassName(domValue, 'highlight');
3780
+ }
3781
+
3782
+ // strip formatting from the contents of the editable div
3783
+ util.stripFormatting(domValue);
3784
+ }
3785
+ };
3786
+
3787
+ /**
3788
+ * Update dom field:
3789
+ * - the text color of the field, depending on the text
3790
+ * - the height of the field, depending on the width
3791
+ * - background color in case it is empty
3792
+ * @private
3793
+ */
3794
+ Node.prototype._updateDomField = function () {
3795
+ var domField = this.dom.field;
3796
+ if (domField) {
3797
+ // make backgound color lightgray when empty
3798
+ var isEmpty = (String(this.field) == '' && this.parent.type != 'array');
3799
+ if (isEmpty) {
3800
+ util.addClassName(domField, 'empty');
3801
+ }
3802
+ else {
3803
+ util.removeClassName(domField, 'empty');
3804
+ }
3805
+
3806
+ // highlight when there is a search result
3807
+ if (this.searchFieldActive) {
3808
+ util.addClassName(domField, 'highlight-active');
3809
+ }
3810
+ else {
3811
+ util.removeClassName(domField, 'highlight-active');
3812
+ }
3813
+ if (this.searchField) {
3814
+ util.addClassName(domField, 'highlight');
3815
+ }
3816
+ else {
3817
+ util.removeClassName(domField, 'highlight');
3818
+ }
3819
+
3820
+ // strip formatting from the contents of the editable div
3821
+ util.stripFormatting(domField);
3822
+ }
3823
+ };
3824
+
3825
+ /**
3826
+ * Retrieve field from DOM
3827
+ * @param {boolean} [silent] If true (default), no errors will be thrown in
3828
+ * case of invalid data
3829
+ * @private
3830
+ */
3831
+ Node.prototype._getDomField = function(silent) {
3832
+ if (this.dom.field && this.fieldEditable) {
3833
+ this.fieldInnerText = util.getInnerText(this.dom.field);
3834
+ }
3835
+
3836
+ if (this.fieldInnerText != undefined) {
3837
+ try {
3838
+ var field = this._unescapeHTML(this.fieldInnerText);
3839
+
3840
+ if (field !== this.field) {
3841
+ var oldField = this.field;
3842
+ this.field = field;
3843
+ this.editor._onAction('editField', {
3844
+ 'node': this,
3845
+ 'oldValue': oldField,
3846
+ 'newValue': field,
3847
+ 'oldSelection': this.editor.selection,
3848
+ 'newSelection': this.editor.getSelection()
3849
+ });
3850
+ }
3851
+ }
3852
+ catch (err) {
3853
+ this.field = undefined;
3854
+ // TODO: sent an action here, with the new, invalid value?
3855
+ if (silent !== true) {
3856
+ throw err;
3857
+ }
3858
+ }
3859
+ }
3860
+ };
3861
+
3862
+ /**
3863
+ * Clear the dom of the node
3864
+ */
3865
+ Node.prototype.clearDom = function() {
3866
+ // TODO: hide the node first?
3867
+ //this.hide();
3868
+ // TODO: recursively clear dom?
3869
+
3870
+ this.dom = {};
3871
+ };
3872
+
3873
+ /**
3874
+ * Get the HTML DOM TR element of the node.
3875
+ * The dom will be generated when not yet created
3876
+ * @return {Element} tr HTML DOM TR Element
3877
+ */
3878
+ Node.prototype.getDom = function() {
3879
+ var dom = this.dom;
3880
+ if (dom.tr) {
3881
+ return dom.tr;
3882
+ }
3883
+
3884
+ this._updateEditability();
3885
+
3886
+ // create row
3887
+ dom.tr = document.createElement('tr');
3888
+ dom.tr.node = this;
3889
+
3890
+ if (this.editor.options.mode === 'tree') { // note: we take here the global setting
3891
+ var tdDrag = document.createElement('td');
3892
+ if (this.editable.field) {
3893
+ // create draggable area
3894
+ if (this.parent) {
3895
+ var domDrag = document.createElement('button');
3896
+ dom.drag = domDrag;
3897
+ domDrag.className = 'dragarea';
3898
+ domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)';
3899
+ tdDrag.appendChild(domDrag);
3900
+ }
3901
+ }
3902
+ dom.tr.appendChild(tdDrag);
3903
+
3904
+ // create context menu
3905
+ var tdMenu = document.createElement('td');
3906
+ var menu = document.createElement('button');
3907
+ dom.menu = menu;
3908
+ menu.className = 'contextmenu';
3909
+ menu.title = 'Click to open the actions menu (Ctrl+M)';
3910
+ tdMenu.appendChild(dom.menu);
3911
+ dom.tr.appendChild(tdMenu);
3912
+ }
3913
+
3914
+ // create tree and field
3915
+ var tdField = document.createElement('td');
3916
+ dom.tr.appendChild(tdField);
3917
+ dom.tree = this._createDomTree();
3918
+ tdField.appendChild(dom.tree);
3919
+
3920
+ this.updateDom({'updateIndexes': true});
3921
+
3922
+ return dom.tr;
3923
+ };
3924
+
3925
+ /**
3926
+ * DragStart event, fired on mousedown on the dragarea at the left side of a Node
3927
+ * @param {Event} event
3928
+ * @private
3929
+ */
3930
+ Node.prototype._onDragStart = function (event) {
3931
+ var node = this;
3932
+ if (!this.mousemove) {
3933
+ this.mousemove = util.addEventListener(document, 'mousemove',
3934
+ function (event) {
3935
+ node._onDrag(event);
3936
+ });
3937
+ }
3938
+
3939
+ if (!this.mouseup) {
3940
+ this.mouseup = util.addEventListener(document, 'mouseup',
3941
+ function (event ) {
3942
+ node._onDragEnd(event);
3943
+ });
3944
+ }
3945
+
3946
+ this.editor.highlighter.lock();
3947
+ this.drag = {
3948
+ 'oldCursor': document.body.style.cursor,
3949
+ 'startParent': this.parent,
3950
+ 'startIndex': this.parent.childs.indexOf(this),
3951
+ 'mouseX': event.pageX,
3952
+ 'level': this.getLevel()
3953
+ };
3954
+ document.body.style.cursor = 'move';
3955
+
3956
+ event.preventDefault();
3957
+ };
3958
+
3959
+ /**
3960
+ * Drag event, fired when moving the mouse while dragging a Node
3961
+ * @param {Event} event
3962
+ * @private
3963
+ */
3964
+ Node.prototype._onDrag = function (event) {
3965
+ // TODO: this method has grown too large. Split it in a number of methods
3966
+ var mouseY = event.pageY;
3967
+ var mouseX = event.pageX;
3968
+
3969
+ var trThis, trPrev, trNext, trFirst, trLast, trRoot;
3970
+ var nodePrev, nodeNext;
3971
+ var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext;
3972
+ var moved = false;
3973
+
3974
+ // TODO: add an ESC option, which resets to the original position
3975
+
3976
+ // move up/down
3977
+ trThis = this.dom.tr;
3978
+ topThis = util.getAbsoluteTop(trThis);
3979
+ heightThis = trThis.offsetHeight;
3980
+ if (mouseY < topThis) {
3981
+ // move up
3982
+ trPrev = trThis;
3983
+ do {
3984
+ trPrev = trPrev.previousSibling;
3985
+ nodePrev = Node.getNodeFromTarget(trPrev);
3986
+ topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0;
3987
+ }
3988
+ while (trPrev && mouseY < topPrev);
3989
+
3990
+ if (nodePrev && !nodePrev.parent) {
3991
+ nodePrev = undefined;
3992
+ }
3993
+
3994
+ if (!nodePrev) {
3995
+ // move to the first node
3996
+ trRoot = trThis.parentNode.firstChild;
3997
+ trPrev = trRoot ? trRoot.nextSibling : undefined;
3998
+ nodePrev = Node.getNodeFromTarget(trPrev);
3999
+ if (nodePrev == this) {
4000
+ nodePrev = undefined;
4001
+ }
4002
+ }
4003
+
4004
+ if (nodePrev) {
4005
+ // check if mouseY is really inside the found node
4006
+ trPrev = nodePrev.dom.tr;
4007
+ topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0;
4008
+ if (mouseY > topPrev + heightThis) {
4009
+ nodePrev = undefined;
4010
+ }
4011
+ }
4012
+
4013
+ if (nodePrev) {
4014
+ nodePrev.parent.moveBefore(this, nodePrev);
4015
+ moved = true;
4016
+ }
4017
+ }
4018
+ else {
4019
+ // move down
4020
+ trLast = (this.expanded && this.append) ? this.append.getDom() : this.dom.tr;
4021
+ trFirst = trLast ? trLast.nextSibling : undefined;
4022
+ if (trFirst) {
4023
+ topFirst = util.getAbsoluteTop(trFirst);
4024
+ trNext = trFirst;
4025
+ do {
4026
+ nodeNext = Node.getNodeFromTarget(trNext);
4027
+ if (trNext) {
4028
+ bottomNext = trNext.nextSibling ?
4029
+ util.getAbsoluteTop(trNext.nextSibling) : 0;
4030
+ heightNext = trNext ? (bottomNext - topFirst) : 0;
4031
+
4032
+ if (nodeNext.parent.childs.length == 1 && nodeNext.parent.childs[0] == this) {
4033
+ // We are about to remove the last child of this parent,
4034
+ // which will make the parents appendNode visible.
4035
+ topThis += 24 - 1;
4036
+ // TODO: dangerous to suppose the height of the appendNode a constant of 24-1 px.
4037
+ }
4038
+ }
4039
+
4040
+ trNext = trNext.nextSibling;
4041
+ }
4042
+ while (trNext && mouseY > topThis + heightNext);
4043
+
4044
+ if (nodeNext && nodeNext.parent) {
4045
+ // calculate the desired level
4046
+ var diffX = (mouseX - this.drag.mouseX);
4047
+ var diffLevel = Math.round(diffX / 24 / 2);
4048
+ var level = this.drag.level + diffLevel; // desired level
4049
+ var levelNext = nodeNext.getLevel(); // level to be
4050
+
4051
+ // find the best fitting level (move upwards over the append nodes)
4052
+ trPrev = nodeNext.dom.tr.previousSibling;
4053
+ while (levelNext < level && trPrev) {
4054
+ nodePrev = Node.getNodeFromTarget(trPrev);
4055
+ if (nodePrev == this || nodePrev._isChildOf(this)) {
4056
+ // neglect itself and its childs
4057
+ }
4058
+ else if (nodePrev instanceof AppendNode) {
4059
+ var childs = nodePrev.parent.childs;
4060
+ if (childs.length > 1 ||
4061
+ (childs.length == 1 && childs[0] != this)) {
4062
+ // non-visible append node of a list of childs
4063
+ // consisting of not only this node (else the
4064
+ // append node will change into a visible "empty"
4065
+ // text when removing this node).
4066
+ nodeNext = Node.getNodeFromTarget(trPrev);
4067
+ levelNext = nodeNext.getLevel();
4068
+ }
4069
+ else {
4070
+ break;
4071
+ }
4072
+ }
4073
+ else {
4074
+ break;
4075
+ }
4076
+
4077
+ trPrev = trPrev.previousSibling;
4078
+ }
4079
+
4080
+ // move the node when its position is changed
4081
+ if (trLast.nextSibling != nodeNext.dom.tr) {
4082
+ nodeNext.parent.moveBefore(this, nodeNext);
4083
+ moved = true;
4084
+ }
4085
+ }
4086
+ }
4087
+ }
4088
+
4089
+ if (moved) {
4090
+ // update the dragging parameters when moved
4091
+ this.drag.mouseX = mouseX;
4092
+ this.drag.level = this.getLevel();
4093
+ }
4094
+
4095
+ // auto scroll when hovering around the top of the editor
4096
+ this.editor.startAutoScroll(mouseY);
4097
+
4098
+ event.preventDefault();
4099
+ };
4100
+
4101
+ /**
4102
+ * Drag event, fired on mouseup after having dragged a node
4103
+ * @param {Event} event
4104
+ * @private
4105
+ */
4106
+ Node.prototype._onDragEnd = function (event) {
4107
+ var params = {
4108
+ 'node': this,
4109
+ 'startParent': this.drag.startParent,
4110
+ 'startIndex': this.drag.startIndex,
4111
+ 'endParent': this.parent,
4112
+ 'endIndex': this.parent.childs.indexOf(this)
4113
+ };
4114
+ if ((params.startParent != params.endParent) ||
4115
+ (params.startIndex != params.endIndex)) {
4116
+ // only register this action if the node is actually moved to another place
4117
+ this.editor._onAction('moveNode', params);
4118
+ }
4119
+
4120
+ document.body.style.cursor = this.drag.oldCursor;
4121
+ this.editor.highlighter.unlock();
4122
+ delete this.drag;
4123
+
4124
+ if (this.mousemove) {
4125
+ util.removeEventListener(document, 'mousemove', this.mousemove);
4126
+ delete this.mousemove;}
4127
+ if (this.mouseup) {
4128
+ util.removeEventListener(document, 'mouseup', this.mouseup);
4129
+ delete this.mouseup;
4130
+ }
4131
+
4132
+ // Stop any running auto scroll
4133
+ this.editor.stopAutoScroll();
4134
+
4135
+ event.preventDefault();
4136
+ };
4137
+
4138
+ /**
4139
+ * Test if this node is a child of an other node
4140
+ * @param {Node} node
4141
+ * @return {boolean} isChild
4142
+ * @private
4143
+ */
4144
+ Node.prototype._isChildOf = function (node) {
4145
+ var n = this.parent;
4146
+ while (n) {
4147
+ if (n == node) {
4148
+ return true;
4149
+ }
4150
+ n = n.parent;
4151
+ }
4152
+
4153
+ return false;
4154
+ };
4155
+
4156
+ /**
4157
+ * Create an editable field
4158
+ * @return {Element} domField
4159
+ * @private
4160
+ */
4161
+ Node.prototype._createDomField = function () {
4162
+ return document.createElement('div');
4163
+ };
4164
+
4165
+ /**
4166
+ * Set highlighting for this node and all its childs.
4167
+ * Only applied to the currently visible (expanded childs)
4168
+ * @param {boolean} highlight
4169
+ */
4170
+ Node.prototype.setHighlight = function (highlight) {
4171
+ if (this.dom.tr) {
4172
+ this.dom.tr.className = (highlight ? 'highlight' : '');
4173
+
4174
+ if (this.append) {
4175
+ this.append.setHighlight(highlight);
4176
+ }
4177
+
4178
+ if (this.childs) {
4179
+ this.childs.forEach(function (child) {
4180
+ child.setHighlight(highlight);
4181
+ });
4182
+ }
4183
+ }
4184
+ };
4185
+
4186
+ /**
4187
+ * Update the value of the node. Only primitive types are allowed, no Object
4188
+ * or Array is allowed.
4189
+ * @param {String | Number | Boolean | null} value
4190
+ */
4191
+ Node.prototype.updateValue = function (value) {
4192
+ this.value = value;
4193
+ this.updateDom();
4194
+ };
4195
+
4196
+ /**
4197
+ * Update the field of the node.
4198
+ * @param {String} field
4199
+ */
4200
+ Node.prototype.updateField = function (field) {
4201
+ this.field = field;
4202
+ this.updateDom();
4203
+ };
4204
+
4205
+ /**
4206
+ * Update the HTML DOM, optionally recursing through the childs
4207
+ * @param {Object} [options] Available parameters:
4208
+ * {boolean} [recurse] If true, the
4209
+ * DOM of the childs will be updated recursively.
4210
+ * False by default.
4211
+ * {boolean} [updateIndexes] If true, the childs
4212
+ * indexes of the node will be updated too. False by
4213
+ * default.
4214
+ */
4215
+ Node.prototype.updateDom = function (options) {
4216
+ // update level indentation
4217
+ var domTree = this.dom.tree;
4218
+ if (domTree) {
4219
+ domTree.style.marginLeft = this.getLevel() * 24 + 'px';
4220
+ }
4221
+
4222
+ // update field
4223
+ var domField = this.dom.field;
4224
+ if (domField) {
4225
+ if (this.fieldEditable) {
4226
+ // parent is an object
4227
+ domField.contentEditable = this.editable.field;
4228
+ domField.spellcheck = false;
4229
+ domField.className = 'field';
4230
+ }
4231
+ else {
4232
+ // parent is an array this is the root node
4233
+ domField.className = 'readonly';
4234
+ }
4235
+
4236
+ var field;
4237
+ if (this.index != undefined) {
4238
+ field = this.index;
4239
+ }
4240
+ else if (this.field != undefined) {
4241
+ field = this.field;
4242
+ }
4243
+ else if (this._hasChilds()) {
4244
+ field = this.type;
4245
+ }
4246
+ else {
4247
+ field = '';
4248
+ }
4249
+ domField.innerHTML = this._escapeHTML(field);
4250
+ }
4251
+
4252
+ // update value
4253
+ var domValue = this.dom.value;
4254
+ if (domValue) {
4255
+ var count = this.childs ? this.childs.length : 0;
4256
+ if (this.type == 'array') {
4257
+ domValue.innerHTML = '[' + count + ']';
4258
+ }
4259
+ else if (this.type == 'object') {
4260
+ domValue.innerHTML = '{' + count + '}';
4261
+ }
4262
+ else {
4263
+ domValue.innerHTML = this._escapeHTML(this.value);
4264
+ }
4265
+ }
4266
+
4267
+ // update field and value
4268
+ this._updateDomField();
4269
+ this._updateDomValue();
4270
+
4271
+ // update childs indexes
4272
+ if (options && options.updateIndexes === true) {
4273
+ // updateIndexes is true or undefined
4274
+ this._updateDomIndexes();
4275
+ }
4276
+
4277
+ if (options && options.recurse === true) {
4278
+ // recurse is true or undefined. update childs recursively
4279
+ if (this.childs) {
4280
+ this.childs.forEach(function (child) {
4281
+ child.updateDom(options);
4282
+ });
4283
+ }
4284
+ }
4285
+
4286
+ // update row with append button
4287
+ if (this.append) {
4288
+ this.append.updateDom();
4289
+ }
4290
+ };
4291
+
4292
+ /**
4293
+ * Update the DOM of the childs of a node: update indexes and undefined field
4294
+ * names.
4295
+ * Only applicable when structure is an array or object
4296
+ * @private
4297
+ */
4298
+ Node.prototype._updateDomIndexes = function () {
4299
+ var domValue = this.dom.value;
4300
+ var childs = this.childs;
4301
+ if (domValue && childs) {
4302
+ if (this.type == 'array') {
4303
+ childs.forEach(function (child, index) {
4304
+ child.index = index;
4305
+ var childField = child.dom.field;
4306
+ if (childField) {
4307
+ childField.innerHTML = index;
4308
+ }
4309
+ });
4310
+ }
4311
+ else if (this.type == 'object') {
4312
+ childs.forEach(function (child) {
4313
+ if (child.index != undefined) {
4314
+ delete child.index;
4315
+
4316
+ if (child.field == undefined) {
4317
+ child.field = '';
4318
+ }
4319
+ }
4320
+ });
4321
+ }
4322
+ }
4323
+ };
4324
+
4325
+ /**
4326
+ * Create an editable value
4327
+ * @private
4328
+ */
4329
+ Node.prototype._createDomValue = function () {
4330
+ var domValue;
4331
+
4332
+ if (this.type == 'array') {
4333
+ domValue = document.createElement('div');
4334
+ domValue.className = 'readonly';
4335
+ domValue.innerHTML = '[...]';
4336
+ }
4337
+ else if (this.type == 'object') {
4338
+ domValue = document.createElement('div');
4339
+ domValue.className = 'readonly';
4340
+ domValue.innerHTML = '{...}';
4341
+ }
4342
+ else {
4343
+ if (!this.editable.value && util.isUrl(this.value)) {
4344
+ // create a link in case of read-only editor and value containing an url
4345
+ domValue = document.createElement('a');
4346
+ domValue.className = 'value';
4347
+ domValue.href = this.value;
4348
+ domValue.target = '_blank';
4349
+ domValue.innerHTML = this._escapeHTML(this.value);
4350
+ }
4351
+ else {
4352
+ // create an editable or read-only div
4353
+ domValue = document.createElement('div');
4354
+ domValue.contentEditable = this.editable.value;
4355
+ domValue.spellcheck = false;
4356
+ domValue.className = 'value';
4357
+ domValue.innerHTML = this._escapeHTML(this.value);
4358
+ }
4359
+ }
4360
+
4361
+ return domValue;
4362
+ };
4363
+
4364
+ /**
4365
+ * Create an expand/collapse button
4366
+ * @return {Element} expand
4367
+ * @private
4368
+ */
4369
+ Node.prototype._createDomExpandButton = function () {
4370
+ // create expand button
4371
+ var expand = document.createElement('button');
4372
+ if (this._hasChilds()) {
4373
+ expand.className = this.expanded ? 'expanded' : 'collapsed';
4374
+ expand.title =
4375
+ 'Click to expand/collapse this field (Ctrl+E). \n' +
4376
+ 'Ctrl+Click to expand/collapse including all childs.';
4377
+ }
4378
+ else {
4379
+ expand.className = 'invisible';
4380
+ expand.title = '';
4381
+ }
4382
+
4383
+ return expand;
4384
+ };
4385
+
4386
+
4387
+ /**
4388
+ * Create a DOM tree element, containing the expand/collapse button
4389
+ * @return {Element} domTree
4390
+ * @private
4391
+ */
4392
+ Node.prototype._createDomTree = function () {
4393
+ var dom = this.dom;
4394
+ var domTree = document.createElement('table');
4395
+ var tbody = document.createElement('tbody');
4396
+ domTree.style.borderCollapse = 'collapse'; // TODO: put in css
4397
+ domTree.className = 'values';
4398
+ domTree.appendChild(tbody);
4399
+ var tr = document.createElement('tr');
4400
+ tbody.appendChild(tr);
4401
+
4402
+ // create expand button
4403
+ var tdExpand = document.createElement('td');
4404
+ tdExpand.className = 'tree';
4405
+ tr.appendChild(tdExpand);
4406
+ dom.expand = this._createDomExpandButton();
4407
+ tdExpand.appendChild(dom.expand);
4408
+ dom.tdExpand = tdExpand;
4409
+
4410
+ // create the field
4411
+ var tdField = document.createElement('td');
4412
+ tdField.className = 'tree';
4413
+ tr.appendChild(tdField);
4414
+ dom.field = this._createDomField();
4415
+ tdField.appendChild(dom.field);
4416
+ dom.tdField = tdField;
4417
+
4418
+ // create a separator
4419
+ var tdSeparator = document.createElement('td');
4420
+ tdSeparator.className = 'tree';
4421
+ tr.appendChild(tdSeparator);
4422
+ if (this.type != 'object' && this.type != 'array') {
4423
+ tdSeparator.appendChild(document.createTextNode(':'));
4424
+ tdSeparator.className = 'separator';
4425
+ }
4426
+ dom.tdSeparator = tdSeparator;
4427
+
4428
+ // create the value
4429
+ var tdValue = document.createElement('td');
4430
+ tdValue.className = 'tree';
4431
+ tr.appendChild(tdValue);
4432
+ dom.value = this._createDomValue();
4433
+ tdValue.appendChild(dom.value);
4434
+ dom.tdValue = tdValue;
4435
+
4436
+ return domTree;
4437
+ };
4438
+
4439
+ /**
4440
+ * Handle an event. The event is catched centrally by the editor
4441
+ * @param {Event} event
4442
+ */
4443
+ Node.prototype.onEvent = function (event) {
4444
+ var type = event.type,
4445
+ target = event.target || event.srcElement,
4446
+ dom = this.dom,
4447
+ node = this,
4448
+ focusNode,
4449
+ expandable = this._hasChilds();
4450
+
4451
+ // check if mouse is on menu or on dragarea.
4452
+ // If so, highlight current row and its childs
4453
+ if (target == dom.drag || target == dom.menu) {
4454
+ if (type == 'mouseover') {
4455
+ this.editor.highlighter.highlight(this);
4456
+ }
4457
+ else if (type == 'mouseout') {
4458
+ this.editor.highlighter.unhighlight();
4459
+ }
4460
+ }
4461
+
4462
+ // drag events
4463
+ if (type == 'mousedown' && target == dom.drag) {
4464
+ this._onDragStart(event);
4465
+ }
4466
+
4467
+ // context menu events
4468
+ if (type == 'click' && target == dom.menu) {
4469
+ var highlighter = node.editor.highlighter;
4470
+ highlighter.highlight(node);
4471
+ highlighter.lock();
4472
+ util.addClassName(dom.menu, 'selected');
4473
+ this.showContextMenu(dom.menu, function () {
4474
+ util.removeClassName(dom.menu, 'selected');
4475
+ highlighter.unlock();
4476
+ highlighter.unhighlight();
4477
+ });
4478
+ }
4479
+
4480
+ // expand events
4481
+ if (type == 'click' && target == dom.expand) {
4482
+ if (expandable) {
4483
+ var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all
4484
+ this._onExpand(recurse);
4485
+ }
4486
+ }
4487
+
4488
+ // value events
4489
+ var domValue = dom.value;
4490
+ if (target == domValue) {
4491
+ //noinspection FallthroughInSwitchStatementJS
4492
+ switch (type) {
4493
+ case 'focus':
4494
+ focusNode = this;
4495
+ break;
4496
+
4497
+ case 'blur':
4498
+ case 'change':
4499
+ this._getDomValue(true);
4500
+ this._updateDomValue();
4501
+ if (this.value) {
4502
+ domValue.innerHTML = this._escapeHTML(this.value);
4503
+ }
4504
+ break;
4505
+
4506
+ case 'input':
4507
+ this._getDomValue(true);
4508
+ this._updateDomValue();
4509
+ break;
4510
+
4511
+ case 'keydown':
4512
+ case 'mousedown':
4513
+ this.editor.selection = this.editor.getSelection();
4514
+ break;
4515
+
4516
+ case 'click':
4517
+ if (event.ctrlKey || !this.editable.value) {
4518
+ if (util.isUrl(this.value)) {
4519
+ window.open(this.value, '_blank');
4520
+ }
4521
+ }
4522
+ break;
4523
+
4524
+ case 'keyup':
4525
+ this._getDomValue(true);
4526
+ this._updateDomValue();
4527
+ break;
4528
+
4529
+ case 'cut':
4530
+ case 'paste':
4531
+ setTimeout(function () {
4532
+ node._getDomValue(true);
4533
+ node._updateDomValue();
4534
+ }, 1);
4535
+ break;
4536
+ }
4537
+ }
4538
+
4539
+ // field events
4540
+ var domField = dom.field;
4541
+ if (target == domField) {
4542
+ switch (type) {
4543
+ case 'focus':
4544
+ focusNode = this;
4545
+ break;
4546
+
4547
+ case 'blur':
4548
+ case 'change':
4549
+ this._getDomField(true);
4550
+ this._updateDomField();
4551
+ if (this.field) {
4552
+ domField.innerHTML = this._escapeHTML(this.field);
4553
+ }
4554
+ break;
4555
+
4556
+ case 'input':
4557
+ this._getDomField(true);
4558
+ this._updateDomField();
4559
+ break;
4560
+
4561
+ case 'keydown':
4562
+ case 'mousedown':
4563
+ this.editor.selection = this.editor.getSelection();
4564
+ break;
4565
+
4566
+ case 'keyup':
4567
+ this._getDomField(true);
4568
+ this._updateDomField();
4569
+ break;
4570
+
4571
+ case 'cut':
4572
+ case 'paste':
4573
+ setTimeout(function () {
4574
+ node._getDomField(true);
4575
+ node._updateDomField();
4576
+ }, 1);
4577
+ break;
4578
+ }
4579
+ }
4580
+
4581
+ // focus
4582
+ // when clicked in whitespace left or right from the field or value, set focus
4583
+ var domTree = dom.tree;
4584
+ if (target == domTree.parentNode) {
4585
+ switch (type) {
4586
+ case 'click':
4587
+ var left = (event.offsetX != undefined) ?
4588
+ (event.offsetX < (this.getLevel() + 1) * 24) :
4589
+ (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF
4590
+ if (left || expandable) {
4591
+ // node is expandable when it is an object or array
4592
+ if (domField) {
4593
+ util.setEndOfContentEditable(domField);
4594
+ domField.focus();
4595
+ }
4596
+ }
4597
+ else {
4598
+ if (domValue) {
4599
+ util.setEndOfContentEditable(domValue);
4600
+ domValue.focus();
4601
+ }
4602
+ }
4603
+ break;
4604
+ }
4605
+ }
4606
+ if ((target == dom.tdExpand && !expandable) || target == dom.tdField ||
4607
+ target == dom.tdSeparator) {
4608
+ switch (type) {
4609
+ case 'click':
4610
+ if (domField) {
4611
+ util.setEndOfContentEditable(domField);
4612
+ domField.focus();
4613
+ }
4614
+ break;
4615
+ }
4616
+ }
4617
+
4618
+ if (type == 'keydown') {
4619
+ this.onKeyDown(event);
4620
+ }
4621
+ };
4622
+
4623
+ /**
4624
+ * Key down event handler
4625
+ * @param {Event} event
4626
+ */
4627
+ Node.prototype.onKeyDown = function (event) {
4628
+ var keynum = event.which || event.keyCode;
4629
+ var target = event.target || event.srcElement;
4630
+ var ctrlKey = event.ctrlKey;
4631
+ var shiftKey = event.shiftKey;
4632
+ var altKey = event.altKey;
4633
+ var handled = false;
4634
+ var prevNode, nextNode, nextDom, nextDom2;
4635
+ var editable = this.editor.options.mode === 'tree';
4636
+
4637
+ // util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
4638
+ if (keynum == 13) { // Enter
4639
+ if (target == this.dom.value) {
4640
+ if (!this.editable.value || event.ctrlKey) {
4641
+ if (util.isUrl(this.value)) {
4642
+ window.open(this.value, '_blank');
4643
+ handled = true;
4644
+ }
4645
+ }
4646
+ }
4647
+ else if (target == this.dom.expand) {
4648
+ var expandable = this._hasChilds();
4649
+ if (expandable) {
4650
+ var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all
4651
+ this._onExpand(recurse);
4652
+ target.focus();
4653
+ handled = true;
4654
+ }
4655
+ }
4656
+ }
4657
+ else if (keynum == 68) { // D
4658
+ if (ctrlKey && editable) { // Ctrl+D
4659
+ this._onDuplicate();
4660
+ handled = true;
4661
+ }
4662
+ }
4663
+ else if (keynum == 69) { // E
4664
+ if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E
4665
+ this._onExpand(shiftKey); // recurse = shiftKey
4666
+ target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline)
4667
+ handled = true;
4668
+ }
4669
+ }
4670
+ else if (keynum == 77 && editable) { // M
4671
+ if (ctrlKey) { // Ctrl+M
4672
+ this.showContextMenu(target);
4673
+ handled = true;
4674
+ }
4675
+ }
4676
+ else if (keynum == 46 && editable) { // Del
4677
+ if (ctrlKey) { // Ctrl+Del
4678
+ this._onRemove();
4679
+ handled = true;
4680
+ }
4681
+ }
4682
+ else if (keynum == 45 && editable) { // Ins
4683
+ if (ctrlKey && !shiftKey) { // Ctrl+Ins
4684
+ this._onInsertBefore();
4685
+ handled = true;
4686
+ }
4687
+ else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins
4688
+ this._onInsertAfter();
4689
+ handled = true;
4690
+ }
4691
+ }
4692
+ else if (keynum == 35) { // End
4693
+ if (altKey) { // Alt+End
4694
+ // find the last node
4695
+ var lastNode = this._lastNode();
4696
+ if (lastNode) {
4697
+ lastNode.focus(Node.focusElement || this._getElementName(target));
4698
+ }
4699
+ handled = true;
4700
+ }
4701
+ }
4702
+ else if (keynum == 36) { // Home
4703
+ if (altKey) { // Alt+Home
4704
+ // find the first node
4705
+ var firstNode = this._firstNode();
4706
+ if (firstNode) {
4707
+ firstNode.focus(Node.focusElement || this._getElementName(target));
4708
+ }
4709
+ handled = true;
4710
+ }
4711
+ }
4712
+ else if (keynum == 37) { // Arrow Left
4713
+ if (altKey && !shiftKey) { // Alt + Arrow Left
4714
+ // move to left element
4715
+ var prevElement = this._previousElement(target);
4716
+ if (prevElement) {
4717
+ this.focus(this._getElementName(prevElement));
4718
+ }
4719
+ handled = true;
4720
+ }
4721
+ else if (altKey && shiftKey && editable) { // Alt + Shift Arrow left
4722
+ if (this.expanded) {
4723
+ var appendDom = this.getAppend();
4724
+ nextDom = appendDom ? appendDom.nextSibling : undefined;
4725
+ }
4726
+ else {
4727
+ var dom = this.getDom();
4728
+ nextDom = dom.nextSibling;
4729
+ }
4730
+ if (nextDom) {
4731
+ nextNode = Node.getNodeFromTarget(nextDom);
4732
+ nextDom2 = nextDom.nextSibling;
4733
+ nextNode2 = Node.getNodeFromTarget(nextDom2);
4734
+ if (nextNode && nextNode instanceof AppendNode &&
4735
+ !(this.parent.childs.length == 1) &&
4736
+ nextNode2 && nextNode2.parent) {
4737
+ nextNode2.parent.moveBefore(this, nextNode2);
4738
+ this.focus(Node.focusElement || this._getElementName(target));
4739
+ }
4740
+ }
4741
+ }
4742
+ }
4743
+ else if (keynum == 38) { // Arrow Up
4744
+ if (altKey && !shiftKey) { // Alt + Arrow Up
4745
+ // find the previous node
4746
+ prevNode = this._previousNode();
4747
+ if (prevNode) {
4748
+ prevNode.focus(Node.focusElement || this._getElementName(target));
4749
+ }
4750
+ handled = true;
4751
+ }
4752
+ else if (altKey && shiftKey) { // Alt + Shift + Arrow Up
4753
+ // find the previous node
4754
+ prevNode = this._previousNode();
4755
+ if (prevNode && prevNode.parent) {
4756
+ prevNode.parent.moveBefore(this, prevNode);
4757
+ this.focus(Node.focusElement || this._getElementName(target));
4758
+ }
4759
+ handled = true;
4760
+ }
4761
+ }
4762
+ else if (keynum == 39) { // Arrow Right
4763
+ if (altKey && !shiftKey) { // Alt + Arrow Right
4764
+ // move to right element
4765
+ var nextElement = this._nextElement(target);
4766
+ if (nextElement) {
4767
+ this.focus(this._getElementName(nextElement));
4768
+ }
4769
+ handled = true;
4770
+ }
4771
+ else if (altKey && shiftKey) { // Alt + Shift Arrow Right
4772
+ dom = this.getDom();
4773
+ var prevDom = dom.previousSibling;
4774
+ if (prevDom) {
4775
+ prevNode = Node.getNodeFromTarget(prevDom);
4776
+ if (prevNode && prevNode.parent &&
4777
+ (prevNode instanceof AppendNode)
4778
+ && !prevNode.isVisible()) {
4779
+ prevNode.parent.moveBefore(this, prevNode);
4780
+ this.focus(Node.focusElement || this._getElementName(target));
4781
+ }
4782
+ }
4783
+ }
4784
+ }
4785
+ else if (keynum == 40) { // Arrow Down
4786
+ if (altKey && !shiftKey) { // Alt + Arrow Down
4787
+ // find the next node
4788
+ nextNode = this._nextNode();
4789
+ if (nextNode) {
4790
+ nextNode.focus(Node.focusElement || this._getElementName(target));
4791
+ }
4792
+ handled = true;
4793
+ }
4794
+ else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down
4795
+ // find the 2nd next node and move before that one
4796
+ if (this.expanded) {
4797
+ nextNode = this.append ? this.append._nextNode() : undefined;
4798
+ }
4799
+ else {
4800
+ nextNode = this._nextNode();
4801
+ }
4802
+ nextDom = nextNode ? nextNode.getDom() : undefined;
4803
+ if (this.parent.childs.length == 1) {
4804
+ nextDom2 = nextDom;
4805
+ }
4806
+ else {
4807
+ nextDom2 = nextDom ? nextDom.nextSibling : undefined;
4808
+ }
4809
+ var nextNode2 = Node.getNodeFromTarget(nextDom2);
4810
+ if (nextNode2 && nextNode2.parent) {
4811
+ nextNode2.parent.moveBefore(this, nextNode2);
4812
+ this.focus(Node.focusElement || this._getElementName(target));
4813
+ }
4814
+ handled = true;
4815
+ }
4816
+ }
4817
+
4818
+ if (handled) {
4819
+ event.preventDefault();
4820
+ event.stopPropagation();
4821
+ }
4822
+ };
4823
+
4824
+ /**
4825
+ * Handle the expand event, when clicked on the expand button
4826
+ * @param {boolean} recurse If true, child nodes will be expanded too
4827
+ * @private
4828
+ */
4829
+ Node.prototype._onExpand = function (recurse) {
4830
+ if (recurse) {
4831
+ // Take the table offline
4832
+ var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this
4833
+ var frame = table.parentNode;
4834
+ var scrollTop = frame.scrollTop;
4835
+ frame.removeChild(table);
4836
+ }
4837
+
4838
+ if (this.expanded) {
4839
+ this.collapse(recurse);
4840
+ }
4841
+ else {
4842
+ this.expand(recurse);
4843
+ }
4844
+
4845
+ if (recurse) {
4846
+ // Put the table online again
4847
+ frame.appendChild(table);
4848
+ frame.scrollTop = scrollTop;
4849
+ }
4850
+ };
4851
+
4852
+ /**
4853
+ * Remove this node
4854
+ * @private
4855
+ */
4856
+ Node.prototype._onRemove = function() {
4857
+ this.editor.highlighter.unhighlight();
4858
+ var childs = this.parent.childs;
4859
+ var index = childs.indexOf(this);
4860
+
4861
+ // adjust the focus
4862
+ var oldSelection = this.editor.getSelection();
4863
+ if (childs[index + 1]) {
4864
+ childs[index + 1].focus();
4865
+ }
4866
+ else if (childs[index - 1]) {
4867
+ childs[index - 1].focus();
4868
+ }
4869
+ else {
4870
+ this.parent.focus();
4871
+ }
4872
+ var newSelection = this.editor.getSelection();
4873
+
4874
+ // remove the node
4875
+ this.parent._remove(this);
4876
+
4877
+ // store history action
4878
+ this.editor._onAction('removeNode', {
4879
+ node: this,
4880
+ parent: this.parent,
4881
+ index: index,
4882
+ oldSelection: oldSelection,
4883
+ newSelection: newSelection
4884
+ });
4885
+ };
4886
+
4887
+ /**
4888
+ * Duplicate this node
4889
+ * @private
4890
+ */
4891
+ Node.prototype._onDuplicate = function() {
4892
+ var oldSelection = this.editor.getSelection();
4893
+ var clone = this.parent._duplicate(this);
4894
+ clone.focus();
4895
+ var newSelection = this.editor.getSelection();
4896
+
4897
+ this.editor._onAction('duplicateNode', {
4898
+ node: this,
4899
+ clone: clone,
4900
+ parent: this.parent,
4901
+ oldSelection: oldSelection,
4902
+ newSelection: newSelection
4903
+ });
4904
+ };
4905
+
4906
+ /**
4907
+ * Handle insert before event
4908
+ * @param {String} [field]
4909
+ * @param {*} [value]
4910
+ * @param {String} [type] Can be 'auto', 'array', 'object', or 'string'
4911
+ * @private
4912
+ */
4913
+ Node.prototype._onInsertBefore = function (field, value, type) {
4914
+ var oldSelection = this.editor.getSelection();
4915
+
4916
+ var newNode = new Node(this.editor, {
4917
+ field: (field != undefined) ? field : '',
4918
+ value: (value != undefined) ? value : '',
4919
+ type: type
4920
+ });
4921
+ newNode.expand(true);
4922
+ this.parent.insertBefore(newNode, this);
4923
+ this.editor.highlighter.unhighlight();
4924
+ newNode.focus('field');
4925
+ var newSelection = this.editor.getSelection();
4926
+
4927
+ this.editor._onAction('insertBeforeNode', {
4928
+ node: newNode,
4929
+ beforeNode: this,
4930
+ parent: this.parent,
4931
+ oldSelection: oldSelection,
4932
+ newSelection: newSelection
4933
+ });
4934
+ };
4935
+
4936
+ /**
4937
+ * Handle insert after event
4938
+ * @param {String} [field]
4939
+ * @param {*} [value]
4940
+ * @param {String} [type] Can be 'auto', 'array', 'object', or 'string'
4941
+ * @private
4942
+ */
4943
+ Node.prototype._onInsertAfter = function (field, value, type) {
4944
+ var oldSelection = this.editor.getSelection();
4945
+
4946
+ var newNode = new Node(this.editor, {
4947
+ field: (field != undefined) ? field : '',
4948
+ value: (value != undefined) ? value : '',
4949
+ type: type
4950
+ });
4951
+ newNode.expand(true);
4952
+ this.parent.insertAfter(newNode, this);
4953
+ this.editor.highlighter.unhighlight();
4954
+ newNode.focus('field');
4955
+ var newSelection = this.editor.getSelection();
4956
+
4957
+ this.editor._onAction('insertAfterNode', {
4958
+ node: newNode,
4959
+ afterNode: this,
4960
+ parent: this.parent,
4961
+ oldSelection: oldSelection,
4962
+ newSelection: newSelection
4963
+ });
4964
+ };
4965
+
4966
+ /**
4967
+ * Handle append event
4968
+ * @param {String} [field]
4969
+ * @param {*} [value]
4970
+ * @param {String} [type] Can be 'auto', 'array', 'object', or 'string'
4971
+ * @private
4972
+ */
4973
+ Node.prototype._onAppend = function (field, value, type) {
4974
+ var oldSelection = this.editor.getSelection();
4975
+
4976
+ var newNode = new Node(this.editor, {
4977
+ field: (field != undefined) ? field : '',
4978
+ value: (value != undefined) ? value : '',
4979
+ type: type
4980
+ });
4981
+ newNode.expand(true);
4982
+ this.parent.appendChild(newNode);
4983
+ this.editor.highlighter.unhighlight();
4984
+ newNode.focus('field');
4985
+ var newSelection = this.editor.getSelection();
4986
+
4987
+ this.editor._onAction('appendNode', {
4988
+ node: newNode,
4989
+ parent: this.parent,
4990
+ oldSelection: oldSelection,
4991
+ newSelection: newSelection
4992
+ });
4993
+ };
4994
+
4995
+ /**
4996
+ * Change the type of the node's value
4997
+ * @param {String} newType
4998
+ * @private
4999
+ */
5000
+ Node.prototype._onChangeType = function (newType) {
5001
+ var oldType = this.type;
5002
+ if (newType != oldType) {
5003
+ var oldSelection = this.editor.getSelection();
5004
+ this.changeType(newType);
5005
+ var newSelection = this.editor.getSelection();
5006
+
5007
+ this.editor._onAction('changeType', {
5008
+ node: this,
5009
+ oldType: oldType,
5010
+ newType: newType,
5011
+ oldSelection: oldSelection,
5012
+ newSelection: newSelection
5013
+ });
5014
+ }
5015
+ };
5016
+
5017
+ /**
5018
+ * Sort the childs of the node. Only applicable when the node has type 'object'
5019
+ * or 'array'.
5020
+ * @param {String} direction Sorting direction. Available values: "asc", "desc"
5021
+ * @private
5022
+ */
5023
+ Node.prototype._onSort = function (direction) {
5024
+ if (this._hasChilds()) {
5025
+ var order = (direction == 'desc') ? -1 : 1;
5026
+ var prop = (this.type == 'array') ? 'value': 'field';
5027
+ this.hideChilds();
5028
+
5029
+ var oldChilds = this.childs;
5030
+ var oldSort = this.sort;
5031
+
5032
+ // copy the array (the old one will be kept for an undo action
5033
+ this.childs = this.childs.concat();
5034
+
5035
+ // sort the arrays
5036
+ this.childs.sort(function (a, b) {
5037
+ if (a[prop] > b[prop]) return order;
5038
+ if (a[prop] < b[prop]) return -order;
5039
+ return 0;
5040
+ });
5041
+ this.sort = (order == 1) ? 'asc' : 'desc';
5042
+
5043
+ this.editor._onAction('sort', {
5044
+ node: this,
5045
+ oldChilds: oldChilds,
5046
+ oldSort: oldSort,
5047
+ newChilds: this.childs,
5048
+ newSort: this.sort
5049
+ });
5050
+
5051
+ this.showChilds();
5052
+ }
5053
+ };
5054
+
5055
+ /**
5056
+ * Create a table row with an append button.
5057
+ * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable
5058
+ */
5059
+ Node.prototype.getAppend = function () {
5060
+ if (!this.append) {
5061
+ this.append = new AppendNode(this.editor);
5062
+ this.append.setParent(this);
5063
+ }
5064
+ return this.append.getDom();
5065
+ };
5066
+
5067
+ /**
5068
+ * Find the node from an event target
5069
+ * @param {Node} target
5070
+ * @return {Node | undefined} node or undefined when not found
5071
+ * @static
5072
+ */
5073
+ Node.getNodeFromTarget = function (target) {
5074
+ while (target) {
5075
+ if (target.node) {
5076
+ return target.node;
5077
+ }
5078
+ target = target.parentNode;
5079
+ }
5080
+
5081
+ return undefined;
5082
+ };
5083
+
5084
+ /**
5085
+ * Get the previously rendered node
5086
+ * @return {Node | null} previousNode
5087
+ * @private
5088
+ */
5089
+ Node.prototype._previousNode = function () {
5090
+ var prevNode = null;
5091
+ var dom = this.getDom();
5092
+ if (dom && dom.parentNode) {
5093
+ // find the previous field
5094
+ var prevDom = dom;
5095
+ do {
5096
+ prevDom = prevDom.previousSibling;
5097
+ prevNode = Node.getNodeFromTarget(prevDom);
5098
+ }
5099
+ while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible()));
5100
+ }
5101
+ return prevNode;
5102
+ };
5103
+
5104
+ /**
5105
+ * Get the next rendered node
5106
+ * @return {Node | null} nextNode
5107
+ * @private
5108
+ */
5109
+ Node.prototype._nextNode = function () {
5110
+ var nextNode = null;
5111
+ var dom = this.getDom();
5112
+ if (dom && dom.parentNode) {
5113
+ // find the previous field
5114
+ var nextDom = dom;
5115
+ do {
5116
+ nextDom = nextDom.nextSibling;
5117
+ nextNode = Node.getNodeFromTarget(nextDom);
5118
+ }
5119
+ while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible()));
5120
+ }
5121
+
5122
+ return nextNode;
5123
+ };
5124
+
5125
+ /**
5126
+ * Get the first rendered node
5127
+ * @return {Node | null} firstNode
5128
+ * @private
5129
+ */
5130
+ Node.prototype._firstNode = function () {
5131
+ var firstNode = null;
5132
+ var dom = this.getDom();
5133
+ if (dom && dom.parentNode) {
5134
+ var firstDom = dom.parentNode.firstChild;
5135
+ firstNode = Node.getNodeFromTarget(firstDom);
5136
+ }
5137
+
5138
+ return firstNode;
5139
+ };
5140
+
5141
+ /**
5142
+ * Get the last rendered node
5143
+ * @return {Node | null} lastNode
5144
+ * @private
5145
+ */
5146
+ Node.prototype._lastNode = function () {
5147
+ var lastNode = null;
5148
+ var dom = this.getDom();
5149
+ if (dom && dom.parentNode) {
5150
+ var lastDom = dom.parentNode.lastChild;
5151
+ lastNode = Node.getNodeFromTarget(lastDom);
5152
+ while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) {
5153
+ lastDom = lastDom.previousSibling;
5154
+ lastNode = Node.getNodeFromTarget(lastDom);
5155
+ }
5156
+ }
5157
+ return lastNode;
5158
+ };
5159
+
5160
+ /**
5161
+ * Get the next element which can have focus.
5162
+ * @param {Element} elem
5163
+ * @return {Element | null} nextElem
5164
+ * @private
5165
+ */
5166
+ Node.prototype._previousElement = function (elem) {
5167
+ var dom = this.dom;
5168
+ // noinspection FallthroughInSwitchStatementJS
5169
+ switch (elem) {
5170
+ case dom.value:
5171
+ if (this.fieldEditable) {
5172
+ return dom.field;
5173
+ }
5174
+ // intentional fall through
5175
+ case dom.field:
5176
+ if (this._hasChilds()) {
5177
+ return dom.expand;
5178
+ }
5179
+ // intentional fall through
5180
+ case dom.expand:
5181
+ return dom.menu;
5182
+ case dom.menu:
5183
+ if (dom.drag) {
5184
+ return dom.drag;
5185
+ }
5186
+ // intentional fall through
5187
+ default:
5188
+ return null;
5189
+ }
5190
+ };
5191
+
5192
+ /**
5193
+ * Get the next element which can have focus.
5194
+ * @param {Element} elem
5195
+ * @return {Element | null} nextElem
5196
+ * @private
5197
+ */
5198
+ Node.prototype._nextElement = function (elem) {
5199
+ var dom = this.dom;
5200
+ // noinspection FallthroughInSwitchStatementJS
5201
+ switch (elem) {
5202
+ case dom.drag:
5203
+ return dom.menu;
5204
+ case dom.menu:
5205
+ if (this._hasChilds()) {
5206
+ return dom.expand;
5207
+ }
5208
+ // intentional fall through
5209
+ case dom.expand:
5210
+ if (this.fieldEditable) {
5211
+ return dom.field;
5212
+ }
5213
+ // intentional fall through
5214
+ case dom.field:
5215
+ if (!this._hasChilds()) {
5216
+ return dom.value;
5217
+ }
5218
+ default:
5219
+ return null;
5220
+ }
5221
+ };
5222
+
5223
+ /**
5224
+ * Get the dom name of given element. returns null if not found.
5225
+ * For example when element == dom.field, "field" is returned.
5226
+ * @param {Element} element
5227
+ * @return {String | null} elementName Available elements with name: 'drag',
5228
+ * 'menu', 'expand', 'field', 'value'
5229
+ * @private
5230
+ */
5231
+ Node.prototype._getElementName = function (element) {
5232
+ var dom = this.dom;
5233
+ for (var name in dom) {
5234
+ if (dom.hasOwnProperty(name)) {
5235
+ if (dom[name] == element) {
5236
+ return name;
5237
+ }
5238
+ }
5239
+ }
5240
+ return null;
5241
+ };
5242
+
5243
+ /**
5244
+ * Test if this node has childs. This is the case when the node is an object
5245
+ * or array.
5246
+ * @return {boolean} hasChilds
5247
+ * @private
5248
+ */
5249
+ Node.prototype._hasChilds = function () {
5250
+ return this.type == 'array' || this.type == 'object';
5251
+ };
5252
+
5253
+ // titles with explanation for the different types
5254
+ Node.TYPE_TITLES = {
5255
+ 'auto': 'Field type "auto". ' +
5256
+ 'The field type is automatically determined from the value ' +
5257
+ 'and can be a string, number, boolean, or null.',
5258
+ 'object': 'Field type "object". ' +
5259
+ 'An object contains an unordered set of key/value pairs.',
5260
+ 'array': 'Field type "array". ' +
5261
+ 'An array contains an ordered collection of values.',
5262
+ 'string': 'Field type "string". ' +
5263
+ 'Field type is not determined from the value, ' +
5264
+ 'but always returned as string.'
5265
+ };
5266
+
5267
+ /**
5268
+ * Show a contextmenu for this node
5269
+ * @param {HTMLElement} anchor Anchor element to attache the context menu to.
5270
+ * @param {function} [onClose] Callback method called when the context menu
5271
+ * is being closed.
5272
+ */
5273
+ Node.prototype.showContextMenu = function (anchor, onClose) {
5274
+ var node = this;
5275
+ var titles = Node.TYPE_TITLES;
5276
+ var items = [];
5277
+
5278
+ if (this.editable.value) {
5279
+ items.push({
5280
+ text: 'Type',
5281
+ title: 'Change the type of this field',
5282
+ className: 'type-' + this.type,
5283
+ submenu: [
5284
+ {
5285
+ text: 'Auto',
5286
+ className: 'type-auto' +
5287
+ (this.type == 'auto' ? ' selected' : ''),
5288
+ title: titles.auto,
5289
+ click: function () {
5290
+ node._onChangeType('auto');
5291
+ }
5292
+ },
5293
+ {
5294
+ text: 'Array',
5295
+ className: 'type-array' +
5296
+ (this.type == 'array' ? ' selected' : ''),
5297
+ title: titles.array,
5298
+ click: function () {
5299
+ node._onChangeType('array');
5300
+ }
5301
+ },
5302
+ {
5303
+ text: 'Object',
5304
+ className: 'type-object' +
5305
+ (this.type == 'object' ? ' selected' : ''),
5306
+ title: titles.object,
5307
+ click: function () {
5308
+ node._onChangeType('object');
5309
+ }
5310
+ },
5311
+ {
5312
+ text: 'String',
5313
+ className: 'type-string' +
5314
+ (this.type == 'string' ? ' selected' : ''),
5315
+ title: titles.string,
5316
+ click: function () {
5317
+ node._onChangeType('string');
5318
+ }
5319
+ }
5320
+ ]
5321
+ });
5322
+ }
5323
+
5324
+ if (this._hasChilds()) {
5325
+ var direction = ((this.sort == 'asc') ? 'desc': 'asc');
5326
+ items.push({
5327
+ text: 'Sort',
5328
+ title: 'Sort the childs of this ' + this.type,
5329
+ className: 'sort-' + direction,
5330
+ click: function () {
5331
+ node._onSort(direction);
5332
+ },
5333
+ submenu: [
5334
+ {
5335
+ text: 'Ascending',
5336
+ className: 'sort-asc',
5337
+ title: 'Sort the childs of this ' + this.type + ' in ascending order',
5338
+ click: function () {
5339
+ node._onSort('asc');
5340
+ }
5341
+ },
5342
+ {
5343
+ text: 'Descending',
5344
+ className: 'sort-desc',
5345
+ title: 'Sort the childs of this ' + this.type +' in descending order',
5346
+ click: function () {
5347
+ node._onSort('desc');
5348
+ }
5349
+ }
5350
+ ]
5351
+ });
5352
+ }
5353
+
5354
+ if (this.parent && this.parent._hasChilds()) {
5355
+ if (items.length) {
5356
+ // create a separator
5357
+ items.push({
5358
+ 'type': 'separator'
5359
+ });
5360
+ }
5361
+
5362
+ // create append button (for last child node only)
5363
+ var childs = node.parent.childs;
5364
+ if (node == childs[childs.length - 1]) {
5365
+ items.push({
5366
+ text: 'Append',
5367
+ title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
5368
+ submenuTitle: 'Select the type of the field to be appended',
5369
+ className: 'append',
5370
+ click: function () {
5371
+ node._onAppend('', '', 'auto');
5372
+ },
5373
+ submenu: [
5374
+ {
5375
+ text: 'Auto',
5376
+ className: 'type-auto',
5377
+ title: titles.auto,
5378
+ click: function () {
5379
+ node._onAppend('', '', 'auto');
5380
+ }
5381
+ },
5382
+ {
5383
+ text: 'Array',
5384
+ className: 'type-array',
5385
+ title: titles.array,
5386
+ click: function () {
5387
+ node._onAppend('', []);
5388
+ }
5389
+ },
5390
+ {
5391
+ text: 'Object',
5392
+ className: 'type-object',
5393
+ title: titles.object,
5394
+ click: function () {
5395
+ node._onAppend('', {});
5396
+ }
5397
+ },
5398
+ {
5399
+ text: 'String',
5400
+ className: 'type-string',
5401
+ title: titles.string,
5402
+ click: function () {
5403
+ node._onAppend('', '', 'string');
5404
+ }
5405
+ }
5406
+ ]
5407
+ });
5408
+ }
5409
+
5410
+ // create insert button
5411
+ items.push({
5412
+ text: 'Insert',
5413
+ title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
5414
+ submenuTitle: 'Select the type of the field to be inserted',
5415
+ className: 'insert',
5416
+ click: function () {
5417
+ node._onInsertBefore('', '', 'auto');
5418
+ },
5419
+ submenu: [
5420
+ {
5421
+ text: 'Auto',
5422
+ className: 'type-auto',
5423
+ title: titles.auto,
5424
+ click: function () {
5425
+ node._onInsertBefore('', '', 'auto');
5426
+ }
5427
+ },
5428
+ {
5429
+ text: 'Array',
5430
+ className: 'type-array',
5431
+ title: titles.array,
5432
+ click: function () {
5433
+ node._onInsertBefore('', []);
5434
+ }
5435
+ },
5436
+ {
5437
+ text: 'Object',
5438
+ className: 'type-object',
5439
+ title: titles.object,
5440
+ click: function () {
5441
+ node._onInsertBefore('', {});
5442
+ }
5443
+ },
5444
+ {
5445
+ text: 'String',
5446
+ className: 'type-string',
5447
+ title: titles.string,
5448
+ click: function () {
5449
+ node._onInsertBefore('', '', 'string');
5450
+ }
5451
+ }
5452
+ ]
5453
+ });
5454
+
5455
+ if (this.editable.field) {
5456
+ // create duplicate button
5457
+ items.push({
5458
+ text: 'Duplicate',
5459
+ title: 'Duplicate this field (Ctrl+D)',
5460
+ className: 'duplicate',
5461
+ click: function () {
5462
+ node._onDuplicate();
5463
+ }
5464
+ });
5465
+
5466
+ // create remove button
5467
+ items.push({
5468
+ text: 'Remove',
5469
+ title: 'Remove this field (Ctrl+Del)',
5470
+ className: 'remove',
5471
+ click: function () {
5472
+ node._onRemove();
5473
+ }
5474
+ });
5475
+ }
5476
+ }
5477
+
5478
+ var menu = new ContextMenu(items, {close: onClose});
5479
+ menu.show(anchor);
5480
+ };
5481
+
5482
+ /**
5483
+ * get the type of a value
5484
+ * @param {*} value
5485
+ * @return {String} type Can be 'object', 'array', 'string', 'auto'
5486
+ * @private
5487
+ */
5488
+ Node.prototype._getType = function(value) {
5489
+ if (value instanceof Array) {
5490
+ return 'array';
5491
+ }
5492
+ if (value instanceof Object) {
5493
+ return 'object';
5494
+ }
5495
+ if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') {
5496
+ return 'string';
5497
+ }
5498
+
5499
+ return 'auto';
5500
+ };
5501
+
5502
+ /**
5503
+ * cast contents of a string to the correct type. This can be a string,
5504
+ * a number, a boolean, etc
5505
+ * @param {String} str
5506
+ * @return {*} castedStr
5507
+ * @private
5508
+ */
5509
+ Node.prototype._stringCast = function(str) {
5510
+ var lower = str.toLowerCase(),
5511
+ num = Number(str), // will nicely fail with '123ab'
5512
+ numFloat = parseFloat(str); // will nicely fail with ' '
5513
+
5514
+ if (str == '') {
5515
+ return '';
5516
+ }
5517
+ else if (lower == 'null') {
5518
+ return null;
5519
+ }
5520
+ else if (lower == 'true') {
5521
+ return true;
5522
+ }
5523
+ else if (lower == 'false') {
5524
+ return false;
5525
+ }
5526
+ else if (!isNaN(num) && !isNaN(numFloat)) {
5527
+ return num;
5528
+ }
5529
+ else {
5530
+ return str;
5531
+ }
5532
+ };
5533
+
5534
+ /**
5535
+ * escape a text, such that it can be displayed safely in an HTML element
5536
+ * @param {String} text
5537
+ * @return {String} escapedText
5538
+ * @private
5539
+ */
5540
+ Node.prototype._escapeHTML = function (text) {
5541
+ var htmlEscaped = String(text)
5542
+ .replace(/</g, '&lt;')
5543
+ .replace(/>/g, '&gt;')
5544
+ .replace(/ /g, ' &nbsp;') // replace double space with an nbsp and space
5545
+ .replace(/^ /, '&nbsp;') // space at start
5546
+ .replace(/ $/, '&nbsp;'); // space at end
5547
+
5548
+ var json = JSON.stringify(htmlEscaped);
5549
+ return json.substring(1, json.length - 1);
5550
+ };
5551
+
5552
+ /**
5553
+ * unescape a string.
5554
+ * @param {String} escapedText
5555
+ * @return {String} text
5556
+ * @private
5557
+ */
5558
+ Node.prototype._unescapeHTML = function (escapedText) {
5559
+ var json = '"' + this._escapeJSON(escapedText) + '"';
5560
+ var htmlEscaped = util.parse(json);
5561
+ return htmlEscaped
5562
+ .replace(/&lt;/g, '<')
5563
+ .replace(/&gt;/g, '>')
5564
+ .replace(/&nbsp;|\u00A0/g, ' ');
5565
+ };
5566
+
5567
+ /**
5568
+ * escape a text to make it a valid JSON string. The method will:
5569
+ * - replace unescaped double quotes with '\"'
5570
+ * - replace unescaped backslash with '\\'
5571
+ * - replace returns with '\n'
5572
+ * @param {String} text
5573
+ * @return {String} escapedText
5574
+ * @private
5575
+ */
5576
+ Node.prototype._escapeJSON = function (text) {
5577
+ // TODO: replace with some smart regex (only when a new solution is faster!)
5578
+ var escaped = '';
5579
+ var i = 0, iMax = text.length;
5580
+ while (i < iMax) {
5581
+ var c = text.charAt(i);
5582
+ if (c == '\n') {
5583
+ escaped += '\\n';
5584
+ }
5585
+ else if (c == '\\') {
5586
+ escaped += c;
5587
+ i++;
5588
+
5589
+ c = text.charAt(i);
5590
+ if ('"\\/bfnrtu'.indexOf(c) == -1) {
5591
+ escaped += '\\'; // no valid escape character
5592
+ }
5593
+ escaped += c;
5594
+ }
5595
+ else if (c == '"') {
5596
+ escaped += '\\"';
5597
+ }
5598
+ else {
5599
+ escaped += c;
5600
+ }
5601
+ i++;
5602
+ }
5603
+
5604
+ return escaped;
5605
+ };
5606
+
5607
+ // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode
5608
+ var AppendNode = appendNodeFactory(Node);
5609
+
5610
+ module.exports = Node;
5611
+
5612
+
5613
+ /***/ },
5614
+ /* 8 */
5615
+ /***/ function(module, exports, __webpack_require__) {
5616
+
5617
+ var ContextMenu = __webpack_require__(10);
5618
+
5619
+ /**
5620
+ * Create a select box to be used in the editor menu's, which allows to switch mode
5621
+ * @param {Object} editor
5622
+ * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view'
5623
+ * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view'
5624
+ * @returns {HTMLElement} box
5625
+ */
5626
+ function createModeSwitcher(editor, modes, current) {
5627
+ // TODO: decouple mode switcher from editor
5628
+
5629
+ /**
5630
+ * Switch the mode of the editor
5631
+ * @param {String} mode
5632
+ */
5633
+ function switchMode(mode) {
5634
+ // switch mode
5635
+ editor.setMode(mode);
5636
+
5637
+ // restore focus on mode box
5638
+ var modeBox = editor.dom && editor.dom.modeBox;
5639
+ if (modeBox) {
5640
+ modeBox.focus();
5641
+ }
5642
+ }
5643
+
5644
+ // available modes
5645
+ var availableModes = {
5646
+ code: {
5647
+ 'text': 'Code',
5648
+ 'title': 'Switch to code highlighter',
5649
+ 'click': function () {
5650
+ switchMode('code')
5651
+ }
5652
+ },
5653
+ form: {
5654
+ 'text': 'Form',
5655
+ 'title': 'Switch to form editor',
5656
+ 'click': function () {
5657
+ switchMode('form');
5658
+ }
5659
+ },
5660
+ text: {
5661
+ 'text': 'Text',
5662
+ 'title': 'Switch to plain text editor',
5663
+ 'click': function () {
5664
+ switchMode('text');
5665
+ }
5666
+ },
5667
+ tree: {
5668
+ 'text': 'Tree',
5669
+ 'title': 'Switch to tree editor',
5670
+ 'click': function () {
5671
+ switchMode('tree');
5672
+ }
5673
+ },
5674
+ view: {
5675
+ 'text': 'View',
5676
+ 'title': 'Switch to tree view',
5677
+ 'click': function () {
5678
+ switchMode('view');
5679
+ }
5680
+ }
5681
+ };
5682
+
5683
+ // list the selected modes
5684
+ var items = [];
5685
+ for (var i = 0; i < modes.length; i++) {
5686
+ var mode = modes[i];
5687
+ var item = availableModes[mode];
5688
+ if (!item) {
5689
+ throw new Error('Unknown mode "' + mode + '"');
5690
+ }
5691
+
5692
+ item.className = 'type-modes' + ((current == mode) ? ' selected' : '');
5693
+ items.push(item);
5694
+ }
5695
+
5696
+ // retrieve the title of current mode
5697
+ var currentMode = availableModes[current];
5698
+ if (!currentMode) {
5699
+ throw new Error('Unknown mode "' + current + '"');
5700
+ }
5701
+ var currentTitle = currentMode.text;
5702
+
5703
+ // create the html element
5704
+ var box = document.createElement('button');
5705
+ box.className = 'modes separator';
5706
+ box.innerHTML = currentTitle + ' &#x25BE;';
5707
+ box.title = 'Switch editor mode';
5708
+ box.onclick = function () {
5709
+ var menu = new ContextMenu(items);
5710
+ menu.show(box);
5711
+ };
5712
+
5713
+ return box;
5714
+ }
5715
+
5716
+ exports.create = createModeSwitcher;
5717
+
5718
+
5719
+ /***/ },
5720
+ /* 9 */
5721
+ /***/ function(module, exports, __webpack_require__) {
5722
+
5723
+ // load brace
5724
+ var ace = __webpack_require__(14);
5725
+
5726
+ // load required ace modules
5727
+ __webpack_require__(15);
5728
+ __webpack_require__(16);
5729
+ __webpack_require__(13);
5730
+
5731
+ module.exports = ace;
5732
+
5733
+
5734
+ /***/ },
5735
+ /* 10 */
5736
+ /***/ function(module, exports, __webpack_require__) {
5737
+
5738
+ var util = __webpack_require__(3);
5739
+
5740
+ /**
5741
+ * A context menu
5742
+ * @param {Object[]} items Array containing the menu structure
5743
+ * TODO: describe structure
5744
+ * @param {Object} [options] Object with options. Available options:
5745
+ * {function} close Callback called when the
5746
+ * context menu is being closed.
5747
+ * @constructor
5748
+ */
5749
+ function ContextMenu (items, options) {
5750
+ this.dom = {};
5751
+
5752
+ var me = this;
5753
+ var dom = this.dom;
5754
+ this.anchor = undefined;
5755
+ this.items = items;
5756
+ this.eventListeners = {};
5757
+ this.selection = undefined; // holds the selection before the menu was opened
5758
+ this.visibleSubmenu = undefined;
5759
+ this.onClose = options ? options.close : undefined;
5760
+
5761
+ // create a container element
5762
+ var menu = document.createElement('div');
5763
+ menu.className = 'jsoneditor-contextmenu';
5764
+ dom.menu = menu;
5765
+
5766
+ // create a list to hold the menu items
5767
+ var list = document.createElement('ul');
5768
+ list.className = 'menu';
5769
+ menu.appendChild(list);
5770
+ dom.list = list;
5771
+ dom.items = []; // list with all buttons
5772
+
5773
+ // create a (non-visible) button to set the focus to the menu
5774
+ var focusButton = document.createElement('button');
5775
+ dom.focusButton = focusButton;
5776
+ var li = document.createElement('li');
5777
+ li.style.overflow = 'hidden';
5778
+ li.style.height = '0';
5779
+ li.appendChild(focusButton);
5780
+ list.appendChild(li);
5781
+
5782
+ function createMenuItems (list, domItems, items) {
5783
+ items.forEach(function (item) {
5784
+ if (item.type == 'separator') {
5785
+ // create a separator
5786
+ var separator = document.createElement('div');
5787
+ separator.className = 'separator';
5788
+ li = document.createElement('li');
5789
+ li.appendChild(separator);
5790
+ list.appendChild(li);
5791
+ }
5792
+ else {
5793
+ var domItem = {};
5794
+
5795
+ // create a menu item
5796
+ var li = document.createElement('li');
5797
+ list.appendChild(li);
5798
+
5799
+ // create a button in the menu item
5800
+ var button = document.createElement('button');
5801
+ button.className = item.className;
5802
+ domItem.button = button;
5803
+ if (item.title) {
5804
+ button.title = item.title;
5805
+ }
5806
+ if (item.click) {
5807
+ button.onclick = function () {
5808
+ me.hide();
5809
+ item.click();
5810
+ };
5811
+ }
5812
+ li.appendChild(button);
5813
+
5814
+ // create the contents of the button
5815
+ if (item.submenu) {
5816
+ // add the icon to the button
5817
+ var divIcon = document.createElement('div');
5818
+ divIcon.className = 'icon';
5819
+ button.appendChild(divIcon);
5820
+ button.appendChild(document.createTextNode(item.text));
5821
+
5822
+ var buttonSubmenu;
5823
+ if (item.click) {
5824
+ // submenu and a button with a click handler
5825
+ button.className += ' default';
5826
+
5827
+ var buttonExpand = document.createElement('button');
5828
+ domItem.buttonExpand = buttonExpand;
5829
+ buttonExpand.className = 'expand';
5830
+ buttonExpand.innerHTML = '<div class="expand"></div>';
5831
+ li.appendChild(buttonExpand);
5832
+ if (item.submenuTitle) {
5833
+ buttonExpand.title = item.submenuTitle;
5834
+ }
5835
+
5836
+ buttonSubmenu = buttonExpand;
5837
+ }
5838
+ else {
5839
+ // submenu and a button without a click handler
5840
+ var divExpand = document.createElement('div');
5841
+ divExpand.className = 'expand';
5842
+ button.appendChild(divExpand);
5843
+
5844
+ buttonSubmenu = button;
5845
+ }
5846
+
5847
+ // attach a handler to expand/collapse the submenu
5848
+ buttonSubmenu.onclick = function () {
5849
+ me._onExpandItem(domItem);
5850
+ buttonSubmenu.focus();
5851
+ };
5852
+
5853
+ // create the submenu
5854
+ var domSubItems = [];
5855
+ domItem.subItems = domSubItems;
5856
+ var ul = document.createElement('ul');
5857
+ domItem.ul = ul;
5858
+ ul.className = 'menu';
5859
+ ul.style.height = '0';
5860
+ li.appendChild(ul);
5861
+ createMenuItems(ul, domSubItems, item.submenu);
5862
+ }
5863
+ else {
5864
+ // no submenu, just a button with clickhandler
5865
+ button.innerHTML = '<div class="icon"></div>' + item.text;
5866
+ }
5867
+
5868
+ domItems.push(domItem);
5869
+ }
5870
+ });
5871
+ }
5872
+ createMenuItems(list, this.dom.items, items);
5873
+
5874
+ // TODO: when the editor is small, show the submenu on the right instead of inline?
5875
+
5876
+ // calculate the max height of the menu with one submenu expanded
5877
+ this.maxHeight = 0; // height in pixels
5878
+ items.forEach(function (item) {
5879
+ var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24;
5880
+ me.maxHeight = Math.max(me.maxHeight, height);
5881
+ });
5882
+ }
5883
+
5884
+ /**
5885
+ * Get the currently visible buttons
5886
+ * @return {Array.<HTMLElement>} buttons
5887
+ * @private
5888
+ */
5889
+ ContextMenu.prototype._getVisibleButtons = function () {
5890
+ var buttons = [];
5891
+ var me = this;
5892
+ this.dom.items.forEach(function (item) {
5893
+ buttons.push(item.button);
5894
+ if (item.buttonExpand) {
5895
+ buttons.push(item.buttonExpand);
5896
+ }
5897
+ if (item.subItems && item == me.expandedItem) {
5898
+ item.subItems.forEach(function (subItem) {
5899
+ buttons.push(subItem.button);
5900
+ if (subItem.buttonExpand) {
5901
+ buttons.push(subItem.buttonExpand);
5902
+ }
5903
+ // TODO: change to fully recursive method
5904
+ });
5905
+ }
5906
+ });
5907
+
5908
+ return buttons;
5909
+ };
5910
+
5911
+ // currently displayed context menu, a singleton. We may only have one visible context menu
5912
+ ContextMenu.visibleMenu = undefined;
5913
+
5914
+ /**
5915
+ * Attach the menu to an anchor
5916
+ * @param {HTMLElement} anchor
5917
+ */
5918
+ ContextMenu.prototype.show = function (anchor) {
5919
+ this.hide();
5920
+
5921
+ // calculate whether the menu fits below the anchor
5922
+ var windowHeight = window.innerHeight,
5923
+ windowScroll = (window.pageYOffset || document.scrollTop || 0),
5924
+ windowBottom = windowHeight + windowScroll,
5925
+ anchorHeight = anchor.offsetHeight,
5926
+ menuHeight = this.maxHeight;
5927
+
5928
+ // position the menu
5929
+ var left = util.getAbsoluteLeft(anchor);
5930
+ var top = util.getAbsoluteTop(anchor);
5931
+ if (top + anchorHeight + menuHeight < windowBottom) {
5932
+ // display the menu below the anchor
5933
+ this.dom.menu.style.left = left + 'px';
5934
+ this.dom.menu.style.top = (top + anchorHeight) + 'px';
5935
+ this.dom.menu.style.bottom = '';
5936
+ }
5937
+ else {
5938
+ // display the menu above the anchor
5939
+ this.dom.menu.style.left = left + 'px';
5940
+ this.dom.menu.style.top = '';
5941
+ this.dom.menu.style.bottom = (windowHeight - top) + 'px';
5942
+ }
5943
+
5944
+ // attach the menu to the document
5945
+ document.body.appendChild(this.dom.menu);
5946
+
5947
+ // create and attach event listeners
5948
+ var me = this;
5949
+ var list = this.dom.list;
5950
+ this.eventListeners.mousedown = util.addEventListener(
5951
+ document, 'mousedown', function (event) {
5952
+ // hide menu on click outside of the menu
5953
+ var target = event.target;
5954
+ if ((target != list) && !me._isChildOf(target, list)) {
5955
+ me.hide();
5956
+ event.stopPropagation();
5957
+ event.preventDefault();
5958
+ }
5959
+ });
5960
+ this.eventListeners.mousewheel = util.addEventListener(
5961
+ document, 'mousewheel', function (event) {
5962
+ // block scrolling when context menu is visible
5963
+ event.stopPropagation();
5964
+ event.preventDefault();
5965
+ });
5966
+ this.eventListeners.keydown = util.addEventListener(
5967
+ document, 'keydown', function (event) {
5968
+ me._onKeyDown(event);
5969
+ });
5970
+
5971
+ // move focus to the first button in the context menu
5972
+ this.selection = util.getSelection();
5973
+ this.anchor = anchor;
5974
+ setTimeout(function () {
5975
+ me.dom.focusButton.focus();
5976
+ }, 0);
5977
+
5978
+ if (ContextMenu.visibleMenu) {
5979
+ ContextMenu.visibleMenu.hide();
5980
+ }
5981
+ ContextMenu.visibleMenu = this;
5982
+ };
5983
+
5984
+ /**
5985
+ * Hide the context menu if visible
5986
+ */
5987
+ ContextMenu.prototype.hide = function () {
5988
+ // remove the menu from the DOM
5989
+ if (this.dom.menu.parentNode) {
5990
+ this.dom.menu.parentNode.removeChild(this.dom.menu);
5991
+ if (this.onClose) {
5992
+ this.onClose();
5993
+ }
5994
+ }
5995
+
5996
+ // remove all event listeners
5997
+ // all event listeners are supposed to be attached to document.
5998
+ for (var name in this.eventListeners) {
5999
+ if (this.eventListeners.hasOwnProperty(name)) {
6000
+ var fn = this.eventListeners[name];
6001
+ if (fn) {
6002
+ util.removeEventListener(document, name, fn);
6003
+ }
6004
+ delete this.eventListeners[name];
6005
+ }
6006
+ }
6007
+
6008
+ if (ContextMenu.visibleMenu == this) {
6009
+ ContextMenu.visibleMenu = undefined;
6010
+ }
6011
+ };
6012
+
6013
+ /**
6014
+ * Expand a submenu
6015
+ * Any currently expanded submenu will be hided.
6016
+ * @param {Object} domItem
6017
+ * @private
6018
+ */
6019
+ ContextMenu.prototype._onExpandItem = function (domItem) {
6020
+ var me = this;
6021
+ var alreadyVisible = (domItem == this.expandedItem);
6022
+
6023
+ // hide the currently visible submenu
6024
+ var expandedItem = this.expandedItem;
6025
+ if (expandedItem) {
6026
+ //var ul = expandedItem.ul;
6027
+ expandedItem.ul.style.height = '0';
6028
+ expandedItem.ul.style.padding = '';
6029
+ setTimeout(function () {
6030
+ if (me.expandedItem != expandedItem) {
6031
+ expandedItem.ul.style.display = '';
6032
+ util.removeClassName(expandedItem.ul.parentNode, 'selected');
6033
+ }
6034
+ }, 300); // timeout duration must match the css transition duration
6035
+ this.expandedItem = undefined;
6036
+ }
6037
+
6038
+ if (!alreadyVisible) {
6039
+ var ul = domItem.ul;
6040
+ ul.style.display = 'block';
6041
+ var height = ul.clientHeight; // force a reflow in Firefox
6042
+ setTimeout(function () {
6043
+ if (me.expandedItem == domItem) {
6044
+ ul.style.height = (ul.childNodes.length * 24) + 'px';
6045
+ ul.style.padding = '5px 10px';
6046
+ }
6047
+ }, 0);
6048
+ util.addClassName(ul.parentNode, 'selected');
6049
+ this.expandedItem = domItem;
6050
+ }
6051
+ };
6052
+
6053
+ /**
6054
+ * Handle onkeydown event
6055
+ * @param {Event} event
6056
+ * @private
6057
+ */
6058
+ ContextMenu.prototype._onKeyDown = function (event) {
6059
+ var target = event.target;
6060
+ var keynum = event.which;
6061
+ var handled = false;
6062
+ var buttons, targetIndex, prevButton, nextButton;
6063
+
6064
+ if (keynum == 27) { // ESC
6065
+ // hide the menu on ESC key
6066
+
6067
+ // restore previous selection and focus
6068
+ if (this.selection) {
6069
+ util.setSelection(this.selection);
6070
+ }
6071
+ if (this.anchor) {
6072
+ this.anchor.focus();
6073
+ }
6074
+
6075
+ this.hide();
6076
+
6077
+ handled = true;
6078
+ }
6079
+ else if (keynum == 9) { // Tab
6080
+ if (!event.shiftKey) { // Tab
6081
+ buttons = this._getVisibleButtons();
6082
+ targetIndex = buttons.indexOf(target);
6083
+ if (targetIndex == buttons.length - 1) {
6084
+ // move to first button
6085
+ buttons[0].focus();
6086
+ handled = true;
6087
+ }
6088
+ }
6089
+ else { // Shift+Tab
6090
+ buttons = this._getVisibleButtons();
6091
+ targetIndex = buttons.indexOf(target);
6092
+ if (targetIndex == 0) {
6093
+ // move to last button
6094
+ buttons[buttons.length - 1].focus();
6095
+ handled = true;
6096
+ }
6097
+ }
6098
+ }
6099
+ else if (keynum == 37) { // Arrow Left
6100
+ if (target.className == 'expand') {
6101
+ buttons = this._getVisibleButtons();
6102
+ targetIndex = buttons.indexOf(target);
6103
+ prevButton = buttons[targetIndex - 1];
6104
+ if (prevButton) {
6105
+ prevButton.focus();
6106
+ }
6107
+ }
6108
+ handled = true;
6109
+ }
6110
+ else if (keynum == 38) { // Arrow Up
6111
+ buttons = this._getVisibleButtons();
6112
+ targetIndex = buttons.indexOf(target);
6113
+ prevButton = buttons[targetIndex - 1];
6114
+ if (prevButton && prevButton.className == 'expand') {
6115
+ // skip expand button
6116
+ prevButton = buttons[targetIndex - 2];
6117
+ }
6118
+ if (!prevButton) {
6119
+ // move to last button
6120
+ prevButton = buttons[buttons.length - 1];
6121
+ }
6122
+ if (prevButton) {
6123
+ prevButton.focus();
6124
+ }
6125
+ handled = true;
6126
+ }
6127
+ else if (keynum == 39) { // Arrow Right
6128
+ buttons = this._getVisibleButtons();
6129
+ targetIndex = buttons.indexOf(target);
6130
+ nextButton = buttons[targetIndex + 1];
6131
+ if (nextButton && nextButton.className == 'expand') {
6132
+ nextButton.focus();
6133
+ }
6134
+ handled = true;
6135
+ }
6136
+ else if (keynum == 40) { // Arrow Down
6137
+ buttons = this._getVisibleButtons();
6138
+ targetIndex = buttons.indexOf(target);
6139
+ nextButton = buttons[targetIndex + 1];
6140
+ if (nextButton && nextButton.className == 'expand') {
6141
+ // skip expand button
6142
+ nextButton = buttons[targetIndex + 2];
6143
+ }
6144
+ if (!nextButton) {
6145
+ // move to first button
6146
+ nextButton = buttons[0];
6147
+ }
6148
+ if (nextButton) {
6149
+ nextButton.focus();
6150
+ handled = true;
6151
+ }
6152
+ handled = true;
6153
+ }
6154
+ // TODO: arrow left and right
6155
+
6156
+ if (handled) {
6157
+ event.stopPropagation();
6158
+ event.preventDefault();
6159
+ }
6160
+ };
6161
+
6162
+ /**
6163
+ * Test if an element is a child of a parent element.
6164
+ * @param {Element} child
6165
+ * @param {Element} parent
6166
+ * @return {boolean} isChild
6167
+ */
6168
+ ContextMenu.prototype._isChildOf = function (child, parent) {
6169
+ var e = child.parentNode;
6170
+ while (e) {
6171
+ if (e == parent) {
6172
+ return true;
6173
+ }
6174
+ e = e.parentNode;
6175
+ }
6176
+
6177
+ return false;
6178
+ };
6179
+
6180
+ module.exports = ContextMenu;
6181
+
6182
+
6183
+ /***/ },
6184
+ /* 11 */
6185
+ /***/ function(module, exports, __webpack_require__) {
6186
+
6187
+ var util = __webpack_require__(3);
6188
+ var ContextMenu = __webpack_require__(10);
6189
+
6190
+ /**
6191
+ * A factory function to create an AppendNode, which depends on a Node
6192
+ * @param {Node} Node
6193
+ */
6194
+ function appendNodeFactory(Node) {
6195
+ /**
6196
+ * @constructor AppendNode
6197
+ * @extends Node
6198
+ * @param {TreeEditor} editor
6199
+ * Create a new AppendNode. This is a special node which is created at the
6200
+ * end of the list with childs for an object or array
6201
+ */
6202
+ function AppendNode (editor) {
6203
+ /** @type {TreeEditor} */
6204
+ this.editor = editor;
6205
+ this.dom = {};
6206
+ }
6207
+
6208
+ AppendNode.prototype = new Node();
6209
+
6210
+ /**
6211
+ * Return a table row with an append button.
6212
+ * @return {Element} dom TR element
6213
+ */
6214
+ AppendNode.prototype.getDom = function () {
6215
+ // TODO: implement a new solution for the append node
6216
+ var dom = this.dom;
6217
+
6218
+ if (dom.tr) {
6219
+ return dom.tr;
6220
+ }
6221
+
6222
+ this._updateEditability();
6223
+
6224
+ // a row for the append button
6225
+ var trAppend = document.createElement('tr');
6226
+ trAppend.node = this;
6227
+ dom.tr = trAppend;
6228
+
6229
+ // TODO: consistent naming
6230
+
6231
+ if (this.editable.field) {
6232
+ // a cell for the dragarea column
6233
+ dom.tdDrag = document.createElement('td');
6234
+
6235
+ // create context menu
6236
+ var tdMenu = document.createElement('td');
6237
+ dom.tdMenu = tdMenu;
6238
+ var menu = document.createElement('button');
6239
+ menu.className = 'contextmenu';
6240
+ menu.title = 'Click to open the actions menu (Ctrl+M)';
6241
+ dom.menu = menu;
6242
+ tdMenu.appendChild(dom.menu);
6243
+ }
6244
+
6245
+ // a cell for the contents (showing text 'empty')
6246
+ var tdAppend = document.createElement('td');
6247
+ var domText = document.createElement('div');
6248
+ domText.innerHTML = '(empty)';
6249
+ domText.className = 'readonly';
6250
+ tdAppend.appendChild(domText);
6251
+ dom.td = tdAppend;
6252
+ dom.text = domText;
6253
+
6254
+ this.updateDom();
6255
+
6256
+ return trAppend;
6257
+ };
6258
+
6259
+ /**
6260
+ * Update the HTML dom of the Node
6261
+ */
6262
+ AppendNode.prototype.updateDom = function () {
6263
+ var dom = this.dom;
6264
+ var tdAppend = dom.td;
6265
+ if (tdAppend) {
6266
+ tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px';
6267
+ // TODO: not so nice hard coded offset
6268
+ }
6269
+
6270
+ var domText = dom.text;
6271
+ if (domText) {
6272
+ domText.innerHTML = '(empty ' + this.parent.type + ')';
6273
+ }
6274
+
6275
+ // attach or detach the contents of the append node:
6276
+ // hide when the parent has childs, show when the parent has no childs
6277
+ var trAppend = dom.tr;
6278
+ if (!this.isVisible()) {
6279
+ if (dom.tr.firstChild) {
6280
+ if (dom.tdDrag) {
6281
+ trAppend.removeChild(dom.tdDrag);
6282
+ }
6283
+ if (dom.tdMenu) {
6284
+ trAppend.removeChild(dom.tdMenu);
6285
+ }
6286
+ trAppend.removeChild(tdAppend);
6287
+ }
6288
+ }
6289
+ else {
6290
+ if (!dom.tr.firstChild) {
6291
+ if (dom.tdDrag) {
6292
+ trAppend.appendChild(dom.tdDrag);
6293
+ }
6294
+ if (dom.tdMenu) {
6295
+ trAppend.appendChild(dom.tdMenu);
6296
+ }
6297
+ trAppend.appendChild(tdAppend);
6298
+ }
6299
+ }
6300
+ };
6301
+
6302
+ /**
6303
+ * Check whether the AppendNode is currently visible.
6304
+ * the AppendNode is visible when its parent has no childs (i.e. is empty).
6305
+ * @return {boolean} isVisible
6306
+ */
6307
+ AppendNode.prototype.isVisible = function () {
6308
+ return (this.parent.childs.length == 0);
6309
+ };
6310
+
6311
+ /**
6312
+ * Show a contextmenu for this node
6313
+ * @param {HTMLElement} anchor The element to attach the menu to.
6314
+ * @param {function} [onClose] Callback method called when the context menu
6315
+ * is being closed.
6316
+ */
6317
+ AppendNode.prototype.showContextMenu = function (anchor, onClose) {
6318
+ var node = this;
6319
+ var titles = Node.TYPE_TITLES;
6320
+ var items = [
6321
+ // create append button
6322
+ {
6323
+ 'text': 'Append',
6324
+ 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
6325
+ 'submenuTitle': 'Select the type of the field to be appended',
6326
+ 'className': 'insert',
6327
+ 'click': function () {
6328
+ node._onAppend('', '', 'auto');
6329
+ },
6330
+ 'submenu': [
6331
+ {
6332
+ 'text': 'Auto',
6333
+ 'className': 'type-auto',
6334
+ 'title': titles.auto,
6335
+ 'click': function () {
6336
+ node._onAppend('', '', 'auto');
6337
+ }
6338
+ },
6339
+ {
6340
+ 'text': 'Array',
6341
+ 'className': 'type-array',
6342
+ 'title': titles.array,
6343
+ 'click': function () {
6344
+ node._onAppend('', []);
6345
+ }
6346
+ },
6347
+ {
6348
+ 'text': 'Object',
6349
+ 'className': 'type-object',
6350
+ 'title': titles.object,
6351
+ 'click': function () {
6352
+ node._onAppend('', {});
6353
+ }
6354
+ },
6355
+ {
6356
+ 'text': 'String',
6357
+ 'className': 'type-string',
6358
+ 'title': titles.string,
6359
+ 'click': function () {
6360
+ node._onAppend('', '', 'string');
6361
+ }
6362
+ }
6363
+ ]
6364
+ }
6365
+ ];
6366
+
6367
+ var menu = new ContextMenu(items, {close: onClose});
6368
+ menu.show(anchor);
6369
+ };
6370
+
6371
+ /**
6372
+ * Handle an event. The event is catched centrally by the editor
6373
+ * @param {Event} event
6374
+ */
6375
+ AppendNode.prototype.onEvent = function (event) {
6376
+ var type = event.type;
6377
+ var target = event.target || event.srcElement;
6378
+ var dom = this.dom;
6379
+
6380
+ // highlight the append nodes parent
6381
+ var menu = dom.menu;
6382
+ if (target == menu) {
6383
+ if (type == 'mouseover') {
6384
+ this.editor.highlighter.highlight(this.parent);
6385
+ }
6386
+ else if (type == 'mouseout') {
6387
+ this.editor.highlighter.unhighlight();
6388
+ }
6389
+ }
6390
+
6391
+ // context menu events
6392
+ if (type == 'click' && target == dom.menu) {
6393
+ var highlighter = this.editor.highlighter;
6394
+ highlighter.highlight(this.parent);
6395
+ highlighter.lock();
6396
+ util.addClassName(dom.menu, 'selected');
6397
+ this.showContextMenu(dom.menu, function () {
6398
+ util.removeClassName(dom.menu, 'selected');
6399
+ highlighter.unlock();
6400
+ highlighter.unhighlight();
6401
+ });
6402
+ }
6403
+
6404
+ if (type == 'keydown') {
6405
+ this.onKeyDown(event);
6406
+ }
6407
+ };
6408
+
6409
+ return AppendNode;
6410
+ }
6411
+
6412
+ module.exports = appendNodeFactory;
6413
+
6414
+
6415
+ /***/ },
6416
+ /* 12 */
6417
+ /***/ function(module, exports, __webpack_require__) {
6418
+
6419
+ /* Jison generated parser */
6420
+ var jsonlint = (function(){
6421
+ var parser = {trace: function trace() { },
6422
+ yy: {},
6423
+ symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
6424
+ terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
6425
+ productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
6426
+ performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
6427
+
6428
+ var $0 = $$.length - 1;
6429
+ switch (yystate) {
6430
+ case 1: // replace escaped characters with actual character
6431
+ this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
6432
+ .replace(/\\n/g,'\n')
6433
+ .replace(/\\r/g,'\r')
6434
+ .replace(/\\t/g,'\t')
6435
+ .replace(/\\v/g,'\v')
6436
+ .replace(/\\f/g,'\f')
6437
+ .replace(/\\b/g,'\b');
6438
+
6439
+ break;
6440
+ case 2:this.$ = Number(yytext);
6441
+ break;
6442
+ case 3:this.$ = null;
6443
+ break;
6444
+ case 4:this.$ = true;
6445
+ break;
6446
+ case 5:this.$ = false;
6447
+ break;
6448
+ case 6:return this.$ = $$[$0-1];
6449
+ break;
6450
+ case 13:this.$ = {};
6451
+ break;
6452
+ case 14:this.$ = $$[$0-1];
6453
+ break;
6454
+ case 15:this.$ = [$$[$0-2], $$[$0]];
6455
+ break;
6456
+ case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
6457
+ break;
6458
+ case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];
6459
+ break;
6460
+ case 18:this.$ = [];
6461
+ break;
6462
+ case 19:this.$ = $$[$0-1];
6463
+ break;
6464
+ case 20:this.$ = [$$[$0]];
6465
+ break;
6466
+ case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
6467
+ break;
6468
+ }
6469
+ },
6470
+ table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],
6471
+ defaultActions: {16:[2,6]},
6472
+ parseError: function parseError(str, hash) {
6473
+ throw new Error(str);
6474
+ },
6475
+ parse: function parse(input) {
6476
+ var self = this,
6477
+ stack = [0],
6478
+ vstack = [null], // semantic value stack
6479
+ lstack = [], // location stack
6480
+ table = this.table,
6481
+ yytext = '',
6482
+ yylineno = 0,
6483
+ yyleng = 0,
6484
+ recovering = 0,
6485
+ TERROR = 2,
6486
+ EOF = 1;
6487
+
6488
+ //this.reductionCount = this.shiftCount = 0;
6489
+
6490
+ this.lexer.setInput(input);
6491
+ this.lexer.yy = this.yy;
6492
+ this.yy.lexer = this.lexer;
6493
+ if (typeof this.lexer.yylloc == 'undefined')
6494
+ this.lexer.yylloc = {};
6495
+ var yyloc = this.lexer.yylloc;
6496
+ lstack.push(yyloc);
6497
+
6498
+ if (typeof this.yy.parseError === 'function')
6499
+ this.parseError = this.yy.parseError;
6500
+
6501
+ function popStack (n) {
6502
+ stack.length = stack.length - 2*n;
6503
+ vstack.length = vstack.length - n;
6504
+ lstack.length = lstack.length - n;
6505
+ }
6506
+
6507
+ function lex() {
6508
+ var token;
6509
+ token = self.lexer.lex() || 1; // $end = 1
6510
+ // if token isn't its numeric value, convert
6511
+ if (typeof token !== 'number') {
6512
+ token = self.symbols_[token] || token;
6513
+ }
6514
+ return token;
6515
+ }
6516
+
6517
+ var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
6518
+ while (true) {
6519
+ // retreive state number from top of stack
6520
+ state = stack[stack.length-1];
6521
+
6522
+ // use default actions if available
6523
+ if (this.defaultActions[state]) {
6524
+ action = this.defaultActions[state];
6525
+ } else {
6526
+ if (symbol == null)
6527
+ symbol = lex();
6528
+ // read action for current state and first input
6529
+ action = table[state] && table[state][symbol];
6530
+ }
6531
+
6532
+ // handle parse error
6533
+ _handle_error:
6534
+ if (typeof action === 'undefined' || !action.length || !action[0]) {
6535
+
6536
+ if (!recovering) {
6537
+ // Report error
6538
+ expected = [];
6539
+ for (p in table[state]) if (this.terminals_[p] && p > 2) {
6540
+ expected.push("'"+this.terminals_[p]+"'");
6541
+ }
6542
+ var errStr = '';
6543
+ if (this.lexer.showPosition) {
6544
+ errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
6545
+ } else {
6546
+ errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
6547
+ (symbol == 1 /*EOF*/ ? "end of input" :
6548
+ ("'"+(this.terminals_[symbol] || symbol)+"'"));
6549
+ }
6550
+ this.parseError(errStr,
6551
+ {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
6552
+ }
6553
+
6554
+ // just recovered from another error
6555
+ if (recovering == 3) {
6556
+ if (symbol == EOF) {
6557
+ throw new Error(errStr || 'Parsing halted.');
6558
+ }
6559
+
6560
+ // discard current lookahead and grab another
6561
+ yyleng = this.lexer.yyleng;
6562
+ yytext = this.lexer.yytext;
6563
+ yylineno = this.lexer.yylineno;
6564
+ yyloc = this.lexer.yylloc;
6565
+ symbol = lex();
6566
+ }
6567
+
6568
+ // try to recover from error
6569
+ while (1) {
6570
+ // check for error recovery rule in this state
6571
+ if ((TERROR.toString()) in table[state]) {
6572
+ break;
6573
+ }
6574
+ if (state == 0) {
6575
+ throw new Error(errStr || 'Parsing halted.');
6576
+ }
6577
+ popStack(1);
6578
+ state = stack[stack.length-1];
6579
+ }
6580
+
6581
+ preErrorSymbol = symbol; // save the lookahead token
6582
+ symbol = TERROR; // insert generic error symbol as new lookahead
6583
+ state = stack[stack.length-1];
6584
+ action = table[state] && table[state][TERROR];
6585
+ recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
6586
+ }
6587
+
6588
+ // this shouldn't happen, unless resolve defaults are off
6589
+ if (action[0] instanceof Array && action.length > 1) {
6590
+ throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
6591
+ }
6592
+
6593
+ switch (action[0]) {
6594
+
6595
+ case 1: // shift
6596
+ //this.shiftCount++;
6597
+
6598
+ stack.push(symbol);
6599
+ vstack.push(this.lexer.yytext);
6600
+ lstack.push(this.lexer.yylloc);
6601
+ stack.push(action[1]); // push state
6602
+ symbol = null;
6603
+ if (!preErrorSymbol) { // normal execution/no error
6604
+ yyleng = this.lexer.yyleng;
6605
+ yytext = this.lexer.yytext;
6606
+ yylineno = this.lexer.yylineno;
6607
+ yyloc = this.lexer.yylloc;
6608
+ if (recovering > 0)
6609
+ recovering--;
6610
+ } else { // error just occurred, resume old lookahead f/ before error
6611
+ symbol = preErrorSymbol;
6612
+ preErrorSymbol = null;
6613
+ }
6614
+ break;
6615
+
6616
+ case 2: // reduce
6617
+ //this.reductionCount++;
6618
+
6619
+ len = this.productions_[action[1]][1];
6620
+
6621
+ // perform semantic action
6622
+ yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
6623
+ // default location, uses first token for firsts, last for lasts
6624
+ yyval._$ = {
6625
+ first_line: lstack[lstack.length-(len||1)].first_line,
6626
+ last_line: lstack[lstack.length-1].last_line,
6627
+ first_column: lstack[lstack.length-(len||1)].first_column,
6628
+ last_column: lstack[lstack.length-1].last_column
6629
+ };
6630
+ r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
6631
+
6632
+ if (typeof r !== 'undefined') {
6633
+ return r;
6634
+ }
6635
+
6636
+ // pop off stack
6637
+ if (len) {
6638
+ stack = stack.slice(0,-1*len*2);
6639
+ vstack = vstack.slice(0, -1*len);
6640
+ lstack = lstack.slice(0, -1*len);
6641
+ }
6642
+
6643
+ stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
6644
+ vstack.push(yyval.$);
6645
+ lstack.push(yyval._$);
6646
+ // goto new state = table[STATE][NONTERMINAL]
6647
+ newState = table[stack[stack.length-2]][stack[stack.length-1]];
6648
+ stack.push(newState);
6649
+ break;
6650
+
6651
+ case 3: // accept
6652
+ return true;
6653
+ }
6654
+
6655
+ }
6656
+
6657
+ return true;
6658
+ }};
6659
+ /* Jison generated lexer */
6660
+ var lexer = (function(){
6661
+ var lexer = ({EOF:1,
6662
+ parseError:function parseError(str, hash) {
6663
+ if (this.yy.parseError) {
6664
+ this.yy.parseError(str, hash);
6665
+ } else {
6666
+ throw new Error(str);
6667
+ }
6668
+ },
6669
+ setInput:function (input) {
6670
+ this._input = input;
6671
+ this._more = this._less = this.done = false;
6672
+ this.yylineno = this.yyleng = 0;
6673
+ this.yytext = this.matched = this.match = '';
6674
+ this.conditionStack = ['INITIAL'];
6675
+ this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
6676
+ return this;
6677
+ },
6678
+ input:function () {
6679
+ var ch = this._input[0];
6680
+ this.yytext+=ch;
6681
+ this.yyleng++;
6682
+ this.match+=ch;
6683
+ this.matched+=ch;
6684
+ var lines = ch.match(/\n/);
6685
+ if (lines) this.yylineno++;
6686
+ this._input = this._input.slice(1);
6687
+ return ch;
6688
+ },
6689
+ unput:function (ch) {
6690
+ this._input = ch + this._input;
6691
+ return this;
6692
+ },
6693
+ more:function () {
6694
+ this._more = true;
6695
+ return this;
6696
+ },
6697
+ less:function (n) {
6698
+ this._input = this.match.slice(n) + this._input;
6699
+ },
6700
+ pastInput:function () {
6701
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
6702
+ return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
6703
+ },
6704
+ upcomingInput:function () {
6705
+ var next = this.match;
6706
+ if (next.length < 20) {
6707
+ next += this._input.substr(0, 20-next.length);
6708
+ }
6709
+ return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
6710
+ },
6711
+ showPosition:function () {
6712
+ var pre = this.pastInput();
6713
+ var c = new Array(pre.length + 1).join("-");
6714
+ return pre + this.upcomingInput() + "\n" + c+"^";
6715
+ },
6716
+ next:function () {
6717
+ if (this.done) {
6718
+ return this.EOF;
6719
+ }
6720
+ if (!this._input) this.done = true;
6721
+
6722
+ var token,
6723
+ match,
6724
+ tempMatch,
6725
+ index,
6726
+ col,
6727
+ lines;
6728
+ if (!this._more) {
6729
+ this.yytext = '';
6730
+ this.match = '';
6731
+ }
6732
+ var rules = this._currentRules();
6733
+ for (var i=0;i < rules.length; i++) {
6734
+ tempMatch = this._input.match(this.rules[rules[i]]);
6735
+ if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
6736
+ match = tempMatch;
6737
+ index = i;
6738
+ if (!this.options.flex) break;
6739
+ }
6740
+ }
6741
+ if (match) {
6742
+ lines = match[0].match(/\n.*/g);
6743
+ if (lines) this.yylineno += lines.length;
6744
+ this.yylloc = {first_line: this.yylloc.last_line,
6745
+ last_line: this.yylineno+1,
6746
+ first_column: this.yylloc.last_column,
6747
+ last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
6748
+ this.yytext += match[0];
6749
+ this.match += match[0];
6750
+ this.yyleng = this.yytext.length;
6751
+ this._more = false;
6752
+ this._input = this._input.slice(match[0].length);
6753
+ this.matched += match[0];
6754
+ token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
6755
+ if (this.done && this._input) this.done = false;
6756
+ if (token) return token;
6757
+ else return;
6758
+ }
6759
+ if (this._input === "") {
6760
+ return this.EOF;
6761
+ } else {
6762
+ this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
6763
+ {text: "", token: null, line: this.yylineno});
6764
+ }
6765
+ },
6766
+ lex:function lex() {
6767
+ var r = this.next();
6768
+ if (typeof r !== 'undefined') {
6769
+ return r;
6770
+ } else {
6771
+ return this.lex();
6772
+ }
6773
+ },
6774
+ begin:function begin(condition) {
6775
+ this.conditionStack.push(condition);
6776
+ },
6777
+ popState:function popState() {
6778
+ return this.conditionStack.pop();
6779
+ },
6780
+ _currentRules:function _currentRules() {
6781
+ return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
6782
+ },
6783
+ topState:function () {
6784
+ return this.conditionStack[this.conditionStack.length-2];
6785
+ },
6786
+ pushState:function begin(condition) {
6787
+ this.begin(condition);
6788
+ }});
6789
+ lexer.options = {};
6790
+ lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
6791
+
6792
+ var YYSTATE=YY_START
6793
+ switch($avoiding_name_collisions) {
6794
+ case 0:/* skip whitespace */
6795
+ break;
6796
+ case 1:return 6
6797
+ break;
6798
+ case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
6799
+ break;
6800
+ case 3:return 17
6801
+ break;
6802
+ case 4:return 18
6803
+ break;
6804
+ case 5:return 23
6805
+ break;
6806
+ case 6:return 24
6807
+ break;
6808
+ case 7:return 22
6809
+ break;
6810
+ case 8:return 21
6811
+ break;
6812
+ case 9:return 10
6813
+ break;
6814
+ case 10:return 11
6815
+ break;
6816
+ case 11:return 8
6817
+ break;
6818
+ case 12:return 14
6819
+ break;
6820
+ case 13:return 'INVALID'
6821
+ break;
6822
+ }
6823
+ };
6824
+ lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/];
6825
+ lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}};
6826
+
6827
+
6828
+ ;
6829
+ return lexer;})()
6830
+ parser.lexer = lexer;
6831
+ return parser;
6832
+ })();
6833
+ if (true) {
6834
+ exports.parser = jsonlint;
6835
+ exports.parse = jsonlint.parse;
6836
+ }
6837
+
6838
+ /***/ },
6839
+ /* 13 */
6840
+ /***/ function(module, exports, __webpack_require__) {
6841
+
6842
+ /* ***** BEGIN LICENSE BLOCK *****
6843
+ * Distributed under the BSD license:
6844
+ *
6845
+ * Copyright (c) 2010, Ajax.org B.V.
6846
+ * All rights reserved.
6847
+ *
6848
+ * Redistribution and use in source and binary forms, with or without
6849
+ * modification, are permitted provided that the following conditions are met:
6850
+ * * Redistributions of source code must retain the above copyright
6851
+ * notice, this list of conditions and the following disclaimer.
6852
+ * * Redistributions in binary form must reproduce the above copyright
6853
+ * notice, this list of conditions and the following disclaimer in the
6854
+ * documentation and/or other materials provided with the distribution.
6855
+ * * Neither the name of Ajax.org B.V. nor the
6856
+ * names of its contributors may be used to endorse or promote products
6857
+ * derived from this software without specific prior written permission.
6858
+ *
6859
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
6860
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6861
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6862
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
6863
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6864
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6865
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6866
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6867
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6868
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6869
+ *
6870
+ * ***** END LICENSE BLOCK ***** */
6871
+
6872
+ ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) {
6873
+
6874
+ exports.isDark = false;
6875
+ exports.cssClass = "ace-jsoneditor";
6876
+ exports.cssText = ".ace-jsoneditor .ace_gutter {\
6877
+ background: #ebebeb;\
6878
+ color: #333\
6879
+ }\
6880
+ \
6881
+ .ace-jsoneditor.ace_editor {\
6882
+ font-family: droid sans mono, monospace, courier new, courier, sans-serif;\
6883
+ line-height: 1.3;\
6884
+ }\
6885
+ .ace-jsoneditor .ace_print-margin {\
6886
+ width: 1px;\
6887
+ background: #e8e8e8\
6888
+ }\
6889
+ .ace-jsoneditor .ace_scroller {\
6890
+ background-color: #FFFFFF\
6891
+ }\
6892
+ .ace-jsoneditor .ace_text-layer {\
6893
+ color: gray\
6894
+ }\
6895
+ .ace-jsoneditor .ace_variable {\
6896
+ color: #1a1a1a\
6897
+ }\
6898
+ .ace-jsoneditor .ace_cursor {\
6899
+ border-left: 2px solid #000000\
6900
+ }\
6901
+ .ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\
6902
+ border-left: 0px;\
6903
+ border-bottom: 1px solid #000000\
6904
+ }\
6905
+ .ace-jsoneditor .ace_marker-layer .ace_selection {\
6906
+ background: #D5DDF6\
6907
+ }\
6908
+ .ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\
6909
+ box-shadow: 0 0 3px 0px #FFFFFF;\
6910
+ border-radius: 2px\
6911
+ }\
6912
+ .ace-jsoneditor .ace_marker-layer .ace_step {\
6913
+ background: rgb(255, 255, 0)\
6914
+ }\
6915
+ .ace-jsoneditor .ace_marker-layer .ace_bracket {\
6916
+ margin: -1px 0 0 -1px;\
6917
+ border: 1px solid #BFBFBF\
6918
+ }\
6919
+ .ace-jsoneditor .ace_marker-layer .ace_active-line {\
6920
+ background: #FFFBD1\
6921
+ }\
6922
+ .ace-jsoneditor .ace_gutter-active-line {\
6923
+ background-color : #dcdcdc\
6924
+ }\
6925
+ .ace-jsoneditor .ace_marker-layer .ace_selected-word {\
6926
+ border: 1px solid #D5DDF6\
6927
+ }\
6928
+ .ace-jsoneditor .ace_invisible {\
6929
+ color: #BFBFBF\
6930
+ }\
6931
+ .ace-jsoneditor .ace_keyword,\
6932
+ .ace-jsoneditor .ace_meta,\
6933
+ .ace-jsoneditor .ace_support.ace_constant.ace_property-value {\
6934
+ color: #AF956F\
6935
+ }\
6936
+ .ace-jsoneditor .ace_keyword.ace_operator {\
6937
+ color: #484848\
6938
+ }\
6939
+ .ace-jsoneditor .ace_keyword.ace_other.ace_unit {\
6940
+ color: #96DC5F\
6941
+ }\
6942
+ .ace-jsoneditor .ace_constant.ace_language {\
6943
+ color: darkorange\
6944
+ }\
6945
+ .ace-jsoneditor .ace_constant.ace_numeric {\
6946
+ color: red\
6947
+ }\
6948
+ .ace-jsoneditor .ace_constant.ace_character.ace_entity {\
6949
+ color: #BF78CC\
6950
+ }\
6951
+ .ace-jsoneditor .ace_invalid {\
6952
+ color: #FFFFFF;\
6953
+ background-color: #FF002A;\
6954
+ }\
6955
+ .ace-jsoneditor .ace_fold {\
6956
+ background-color: #AF956F;\
6957
+ border-color: #000000\
6958
+ }\
6959
+ .ace-jsoneditor .ace_storage,\
6960
+ .ace-jsoneditor .ace_support.ace_class,\
6961
+ .ace-jsoneditor .ace_support.ace_function,\
6962
+ .ace-jsoneditor .ace_support.ace_other,\
6963
+ .ace-jsoneditor .ace_support.ace_type {\
6964
+ color: #C52727\
6965
+ }\
6966
+ .ace-jsoneditor .ace_string {\
6967
+ color: green\
6968
+ }\
6969
+ .ace-jsoneditor .ace_comment {\
6970
+ color: #BCC8BA\
6971
+ }\
6972
+ .ace-jsoneditor .ace_entity.ace_name.ace_tag,\
6973
+ .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\
6974
+ color: #606060\
6975
+ }\
6976
+ .ace-jsoneditor .ace_markup.ace_underline {\
6977
+ text-decoration: underline\
6978
+ }\
6979
+ .ace-jsoneditor .ace_indent-guide {\
6980
+ background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\
6981
+ }";
6982
+
6983
+ var dom = acequire("../lib/dom");
6984
+ dom.importCssString(exports.cssText, exports.cssClass);
6985
+ });
6986
+
6987
+
6988
+ /***/ },
6989
+ /* 14 */
6990
+ /***/ function(module, exports, __webpack_require__) {
6991
+
6992
+ /* ***** BEGIN LICENSE BLOCK *****
6993
+ * Distributed under the BSD license:
6994
+ *
6995
+ * Copyright (c) 2010, Ajax.org B.V.
6996
+ * All rights reserved.
6997
+ *
6998
+ * Redistribution and use in source and binary forms, with or without
6999
+ * modification, are permitted provided that the following conditions are met:
7000
+ * * Redistributions of source code must retain the above copyright
7001
+ * notice, this list of conditions and the following disclaimer.
7002
+ * * Redistributions in binary form must reproduce the above copyright
7003
+ * notice, this list of conditions and the following disclaimer in the
7004
+ * documentation and/or other materials provided with the distribution.
7005
+ * * Neither the name of Ajax.org B.V. nor the
7006
+ * names of its contributors may be used to endorse or promote products
7007
+ * derived from this software without specific prior written permission.
7008
+ *
7009
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7010
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7011
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7012
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
7013
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7014
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7015
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7016
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7017
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7018
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7019
+ *
7020
+ * ***** END LICENSE BLOCK ***** */
7021
+
7022
+ /**
7023
+ * Define a module along with a payload
7024
+ * @param module a name for the payload
7025
+ * @param payload a function to call with (acequire, exports, module) params
7026
+ */
7027
+
7028
+ (function() {
7029
+
7030
+ var ACE_NAMESPACE = "ace";
7031
+
7032
+ var global = (function() {
7033
+ return this;
7034
+ })();
7035
+
7036
+
7037
+ if (!ACE_NAMESPACE && typeof acequirejs !== "undefined")
7038
+ return;
7039
+
7040
+
7041
+ var _define = function(module, deps, payload) {
7042
+ if (typeof module !== 'string') {
7043
+ if (_define.original)
7044
+ _define.original.apply(window, arguments);
7045
+ else {
7046
+ console.error('dropping module because define wasn\'t a string.');
7047
+ console.trace();
7048
+ }
7049
+ return;
7050
+ }
7051
+
7052
+ if (arguments.length == 2)
7053
+ payload = deps;
7054
+
7055
+ if (!_define.modules) {
7056
+ _define.modules = {};
7057
+ _define.payloads = {};
7058
+ }
7059
+
7060
+ _define.payloads[module] = payload;
7061
+ _define.modules[module] = null;
7062
+ };
7063
+
7064
+ /**
7065
+ * Get at functionality ace.define()ed using the function above
7066
+ */
7067
+ var _acequire = function(parentId, module, callback) {
7068
+ if (Object.prototype.toString.call(module) === "[object Array]") {
7069
+ var params = [];
7070
+ for (var i = 0, l = module.length; i < l; ++i) {
7071
+ var dep = lookup(parentId, module[i]);
7072
+ if (!dep && _acequire.original)
7073
+ return _acequire.original.apply(window, arguments);
7074
+ params.push(dep);
7075
+ }
7076
+ if (callback) {
7077
+ callback.apply(null, params);
7078
+ }
7079
+ }
7080
+ else if (typeof module === 'string') {
7081
+ var payload = lookup(parentId, module);
7082
+ if (!payload && _acequire.original)
7083
+ return _acequire.original.apply(window, arguments);
7084
+
7085
+ if (callback) {
7086
+ callback();
7087
+ }
7088
+
7089
+ return payload;
7090
+ }
7091
+ else {
7092
+ if (_acequire.original)
7093
+ return _acequire.original.apply(window, arguments);
7094
+ }
7095
+ };
7096
+
7097
+ var normalizeModule = function(parentId, moduleName) {
7098
+ // normalize plugin acequires
7099
+ if (moduleName.indexOf("!") !== -1) {
7100
+ var chunks = moduleName.split("!");
7101
+ return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
7102
+ }
7103
+ // normalize relative acequires
7104
+ if (moduleName.charAt(0) == ".") {
7105
+ var base = parentId.split("/").slice(0, -1).join("/");
7106
+ moduleName = base + "/" + moduleName;
7107
+
7108
+ while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
7109
+ var previous = moduleName;
7110
+ moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
7111
+ }
7112
+ }
7113
+
7114
+ return moduleName;
7115
+ };
7116
+
7117
+ /**
7118
+ * Internal function to lookup moduleNames and resolve them by calling the
7119
+ * definition function if needed.
7120
+ */
7121
+ var lookup = function(parentId, moduleName) {
7122
+
7123
+ moduleName = normalizeModule(parentId, moduleName);
7124
+
7125
+ var module = _define.modules[moduleName];
7126
+ if (!module) {
7127
+ module = _define.payloads[moduleName];
7128
+ if (typeof module === 'function') {
7129
+ var exports = {};
7130
+ var mod = {
7131
+ id: moduleName,
7132
+ uri: '',
7133
+ exports: exports,
7134
+ packaged: true
7135
+ };
7136
+
7137
+ var req = function(module, callback) {
7138
+ return _acequire(moduleName, module, callback);
7139
+ };
7140
+
7141
+ var returnValue = module(req, exports, mod);
7142
+ exports = returnValue || mod.exports;
7143
+ _define.modules[moduleName] = exports;
7144
+ delete _define.payloads[moduleName];
7145
+ }
7146
+ module = _define.modules[moduleName] = exports || module;
7147
+ }
7148
+ return module;
7149
+ };
7150
+
7151
+ function exportAce(ns) {
7152
+ var acequire = function(module, callback) {
7153
+ return _acequire("", module, callback);
7154
+ };
7155
+
7156
+ var root = global;
7157
+ if (ns) {
7158
+ if (!global[ns])
7159
+ global[ns] = {};
7160
+ root = global[ns];
7161
+ }
7162
+
7163
+ if (!root.define || !root.define.packaged) {
7164
+ _define.original = root.define;
7165
+ root.define = _define;
7166
+ root.define.packaged = true;
7167
+ }
7168
+
7169
+ if (!root.acequire || !root.acequire.packaged) {
7170
+ _acequire.original = root.acequire;
7171
+ root.acequire = acequire;
7172
+ root.acequire.packaged = true;
7173
+ }
7174
+ }
7175
+
7176
+ exportAce(ACE_NAMESPACE);
7177
+
7178
+ })();
7179
+
7180
+ ace.define("ace/lib/regexp",["require","exports","module"], function(acequire, exports, module) {
7181
+ "use strict";
7182
+
7183
+ var real = {
7184
+ exec: RegExp.prototype.exec,
7185
+ test: RegExp.prototype.test,
7186
+ match: String.prototype.match,
7187
+ replace: String.prototype.replace,
7188
+ split: String.prototype.split
7189
+ },
7190
+ compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
7191
+ compliantLastIndexIncrement = function () {
7192
+ var x = /^/g;
7193
+ real.test.call(x, "");
7194
+ return !x.lastIndex;
7195
+ }();
7196
+
7197
+ if (compliantLastIndexIncrement && compliantExecNpcg)
7198
+ return;
7199
+ RegExp.prototype.exec = function (str) {
7200
+ var match = real.exec.apply(this, arguments),
7201
+ name, r2;
7202
+ if ( typeof(str) == 'string' && match) {
7203
+ if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
7204
+ r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", ""));
7205
+ real.replace.call(str.slice(match.index), r2, function () {
7206
+ for (var i = 1; i < arguments.length - 2; i++) {
7207
+ if (arguments[i] === undefined)
7208
+ match[i] = undefined;
7209
+ }
7210
+ });
7211
+ }
7212
+ if (this._xregexp && this._xregexp.captureNames) {
7213
+ for (var i = 1; i < match.length; i++) {
7214
+ name = this._xregexp.captureNames[i - 1];
7215
+ if (name)
7216
+ match[name] = match[i];
7217
+ }
7218
+ }
7219
+ if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
7220
+ this.lastIndex--;
7221
+ }
7222
+ return match;
7223
+ };
7224
+ if (!compliantLastIndexIncrement) {
7225
+ RegExp.prototype.test = function (str) {
7226
+ var match = real.exec.call(this, str);
7227
+ if (match && this.global && !match[0].length && (this.lastIndex > match.index))
7228
+ this.lastIndex--;
7229
+ return !!match;
7230
+ };
7231
+ }
7232
+
7233
+ function getNativeFlags (regex) {
7234
+ return (regex.global ? "g" : "") +
7235
+ (regex.ignoreCase ? "i" : "") +
7236
+ (regex.multiline ? "m" : "") +
7237
+ (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3
7238
+ (regex.sticky ? "y" : "");
7239
+ }
7240
+
7241
+ function indexOf (array, item, from) {
7242
+ if (Array.prototype.indexOf) // Use the native array method if available
7243
+ return array.indexOf(item, from);
7244
+ for (var i = from || 0; i < array.length; i++) {
7245
+ if (array[i] === item)
7246
+ return i;
7247
+ }
7248
+ return -1;
7249
+ }
7250
+
7251
+ });
7252
+
7253
+ ace.define("ace/lib/es5-shim",["require","exports","module"], function(acequire, exports, module) {
7254
+
7255
+ function Empty() {}
7256
+
7257
+ if (!Function.prototype.bind) {
7258
+ Function.prototype.bind = function bind(that) { // .length is 1
7259
+ var target = this;
7260
+ if (typeof target != "function") {
7261
+ throw new TypeError("Function.prototype.bind called on incompatible " + target);
7262
+ }
7263
+ var args = slice.call(arguments, 1); // for normal call
7264
+ var bound = function () {
7265
+
7266
+ if (this instanceof bound) {
7267
+
7268
+ var result = target.apply(
7269
+ this,
7270
+ args.concat(slice.call(arguments))
7271
+ );
7272
+ if (Object(result) === result) {
7273
+ return result;
7274
+ }
7275
+ return this;
7276
+
7277
+ } else {
7278
+ return target.apply(
7279
+ that,
7280
+ args.concat(slice.call(arguments))
7281
+ );
7282
+
7283
+ }
7284
+
7285
+ };
7286
+ if(target.prototype) {
7287
+ Empty.prototype = target.prototype;
7288
+ bound.prototype = new Empty();
7289
+ Empty.prototype = null;
7290
+ }
7291
+ return bound;
7292
+ };
7293
+ }
7294
+ var call = Function.prototype.call;
7295
+ var prototypeOfArray = Array.prototype;
7296
+ var prototypeOfObject = Object.prototype;
7297
+ var slice = prototypeOfArray.slice;
7298
+ var _toString = call.bind(prototypeOfObject.toString);
7299
+ var owns = call.bind(prototypeOfObject.hasOwnProperty);
7300
+ var defineGetter;
7301
+ var defineSetter;
7302
+ var lookupGetter;
7303
+ var lookupSetter;
7304
+ var supportsAccessors;
7305
+ if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
7306
+ defineGetter = call.bind(prototypeOfObject.__defineGetter__);
7307
+ defineSetter = call.bind(prototypeOfObject.__defineSetter__);
7308
+ lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
7309
+ lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
7310
+ }
7311
+ if ([1,2].splice(0).length != 2) {
7312
+ if(function() { // test IE < 9 to splice bug - see issue #138
7313
+ function makeArray(l) {
7314
+ var a = new Array(l+2);
7315
+ a[0] = a[1] = 0;
7316
+ return a;
7317
+ }
7318
+ var array = [], lengthBefore;
7319
+
7320
+ array.splice.apply(array, makeArray(20));
7321
+ array.splice.apply(array, makeArray(26));
7322
+
7323
+ lengthBefore = array.length; //46
7324
+ array.splice(5, 0, "XXX"); // add one element
7325
+
7326
+ lengthBefore + 1 == array.length
7327
+
7328
+ if (lengthBefore + 1 == array.length) {
7329
+ return true;// has right splice implementation without bugs
7330
+ }
7331
+ }()) {//IE 6/7
7332
+ var array_splice = Array.prototype.splice;
7333
+ Array.prototype.splice = function(start, deleteCount) {
7334
+ if (!arguments.length) {
7335
+ return [];
7336
+ } else {
7337
+ return array_splice.apply(this, [
7338
+ start === void 0 ? 0 : start,
7339
+ deleteCount === void 0 ? (this.length - start) : deleteCount
7340
+ ].concat(slice.call(arguments, 2)))
7341
+ }
7342
+ };
7343
+ } else {//IE8
7344
+ Array.prototype.splice = function(pos, removeCount){
7345
+ var length = this.length;
7346
+ if (pos > 0) {
7347
+ if (pos > length)
7348
+ pos = length;
7349
+ } else if (pos == void 0) {
7350
+ pos = 0;
7351
+ } else if (pos < 0) {
7352
+ pos = Math.max(length + pos, 0);
7353
+ }
7354
+
7355
+ if (!(pos+removeCount < length))
7356
+ removeCount = length - pos;
7357
+
7358
+ var removed = this.slice(pos, pos+removeCount);
7359
+ var insert = slice.call(arguments, 2);
7360
+ var add = insert.length;
7361
+ if (pos === length) {
7362
+ if (add) {
7363
+ this.push.apply(this, insert);
7364
+ }
7365
+ } else {
7366
+ var remove = Math.min(removeCount, length - pos);
7367
+ var tailOldPos = pos + remove;
7368
+ var tailNewPos = tailOldPos + add - remove;
7369
+ var tailCount = length - tailOldPos;
7370
+ var lengthAfterRemove = length - remove;
7371
+
7372
+ if (tailNewPos < tailOldPos) { // case A
7373
+ for (var i = 0; i < tailCount; ++i) {
7374
+ this[tailNewPos+i] = this[tailOldPos+i];
7375
+ }
7376
+ } else if (tailNewPos > tailOldPos) { // case B
7377
+ for (i = tailCount; i--; ) {
7378
+ this[tailNewPos+i] = this[tailOldPos+i];
7379
+ }
7380
+ } // else, add == remove (nothing to do)
7381
+
7382
+ if (add && pos === lengthAfterRemove) {
7383
+ this.length = lengthAfterRemove; // truncate array
7384
+ this.push.apply(this, insert);
7385
+ } else {
7386
+ this.length = lengthAfterRemove + add; // reserves space
7387
+ for (i = 0; i < add; ++i) {
7388
+ this[pos+i] = insert[i];
7389
+ }
7390
+ }
7391
+ }
7392
+ return removed;
7393
+ };
7394
+ }
7395
+ }
7396
+ if (!Array.isArray) {
7397
+ Array.isArray = function isArray(obj) {
7398
+ return _toString(obj) == "[object Array]";
7399
+ };
7400
+ }
7401
+ var boxedString = Object("a"),
7402
+ splitString = boxedString[0] != "a" || !(0 in boxedString);
7403
+
7404
+ if (!Array.prototype.forEach) {
7405
+ Array.prototype.forEach = function forEach(fun /*, thisp*/) {
7406
+ var object = toObject(this),
7407
+ self = splitString && _toString(this) == "[object String]" ?
7408
+ this.split("") :
7409
+ object,
7410
+ thisp = arguments[1],
7411
+ i = -1,
7412
+ length = self.length >>> 0;
7413
+ if (_toString(fun) != "[object Function]") {
7414
+ throw new TypeError(); // TODO message
7415
+ }
7416
+
7417
+ while (++i < length) {
7418
+ if (i in self) {
7419
+ fun.call(thisp, self[i], i, object);
7420
+ }
7421
+ }
7422
+ };
7423
+ }
7424
+ if (!Array.prototype.map) {
7425
+ Array.prototype.map = function map(fun /*, thisp*/) {
7426
+ var object = toObject(this),
7427
+ self = splitString && _toString(this) == "[object String]" ?
7428
+ this.split("") :
7429
+ object,
7430
+ length = self.length >>> 0,
7431
+ result = Array(length),
7432
+ thisp = arguments[1];
7433
+ if (_toString(fun) != "[object Function]") {
7434
+ throw new TypeError(fun + " is not a function");
7435
+ }
7436
+
7437
+ for (var i = 0; i < length; i++) {
7438
+ if (i in self)
7439
+ result[i] = fun.call(thisp, self[i], i, object);
7440
+ }
7441
+ return result;
7442
+ };
7443
+ }
7444
+ if (!Array.prototype.filter) {
7445
+ Array.prototype.filter = function filter(fun /*, thisp */) {
7446
+ var object = toObject(this),
7447
+ self = splitString && _toString(this) == "[object String]" ?
7448
+ this.split("") :
7449
+ object,
7450
+ length = self.length >>> 0,
7451
+ result = [],
7452
+ value,
7453
+ thisp = arguments[1];
7454
+ if (_toString(fun) != "[object Function]") {
7455
+ throw new TypeError(fun + " is not a function");
7456
+ }
7457
+
7458
+ for (var i = 0; i < length; i++) {
7459
+ if (i in self) {
7460
+ value = self[i];
7461
+ if (fun.call(thisp, value, i, object)) {
7462
+ result.push(value);
7463
+ }
7464
+ }
7465
+ }
7466
+ return result;
7467
+ };
7468
+ }
7469
+ if (!Array.prototype.every) {
7470
+ Array.prototype.every = function every(fun /*, thisp */) {
7471
+ var object = toObject(this),
7472
+ self = splitString && _toString(this) == "[object String]" ?
7473
+ this.split("") :
7474
+ object,
7475
+ length = self.length >>> 0,
7476
+ thisp = arguments[1];
7477
+ if (_toString(fun) != "[object Function]") {
7478
+ throw new TypeError(fun + " is not a function");
7479
+ }
7480
+
7481
+ for (var i = 0; i < length; i++) {
7482
+ if (i in self && !fun.call(thisp, self[i], i, object)) {
7483
+ return false;
7484
+ }
7485
+ }
7486
+ return true;
7487
+ };
7488
+ }
7489
+ if (!Array.prototype.some) {
7490
+ Array.prototype.some = function some(fun /*, thisp */) {
7491
+ var object = toObject(this),
7492
+ self = splitString && _toString(this) == "[object String]" ?
7493
+ this.split("") :
7494
+ object,
7495
+ length = self.length >>> 0,
7496
+ thisp = arguments[1];
7497
+ if (_toString(fun) != "[object Function]") {
7498
+ throw new TypeError(fun + " is not a function");
7499
+ }
7500
+
7501
+ for (var i = 0; i < length; i++) {
7502
+ if (i in self && fun.call(thisp, self[i], i, object)) {
7503
+ return true;
7504
+ }
7505
+ }
7506
+ return false;
7507
+ };
7508
+ }
7509
+ if (!Array.prototype.reduce) {
7510
+ Array.prototype.reduce = function reduce(fun /*, initial*/) {
7511
+ var object = toObject(this),
7512
+ self = splitString && _toString(this) == "[object String]" ?
7513
+ this.split("") :
7514
+ object,
7515
+ length = self.length >>> 0;
7516
+ if (_toString(fun) != "[object Function]") {
7517
+ throw new TypeError(fun + " is not a function");
7518
+ }
7519
+ if (!length && arguments.length == 1) {
7520
+ throw new TypeError("reduce of empty array with no initial value");
7521
+ }
7522
+
7523
+ var i = 0;
7524
+ var result;
7525
+ if (arguments.length >= 2) {
7526
+ result = arguments[1];
7527
+ } else {
7528
+ do {
7529
+ if (i in self) {
7530
+ result = self[i++];
7531
+ break;
7532
+ }
7533
+ if (++i >= length) {
7534
+ throw new TypeError("reduce of empty array with no initial value");
7535
+ }
7536
+ } while (true);
7537
+ }
7538
+
7539
+ for (; i < length; i++) {
7540
+ if (i in self) {
7541
+ result = fun.call(void 0, result, self[i], i, object);
7542
+ }
7543
+ }
7544
+
7545
+ return result;
7546
+ };
7547
+ }
7548
+ if (!Array.prototype.reduceRight) {
7549
+ Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
7550
+ var object = toObject(this),
7551
+ self = splitString && _toString(this) == "[object String]" ?
7552
+ this.split("") :
7553
+ object,
7554
+ length = self.length >>> 0;
7555
+ if (_toString(fun) != "[object Function]") {
7556
+ throw new TypeError(fun + " is not a function");
7557
+ }
7558
+ if (!length && arguments.length == 1) {
7559
+ throw new TypeError("reduceRight of empty array with no initial value");
7560
+ }
7561
+
7562
+ var result, i = length - 1;
7563
+ if (arguments.length >= 2) {
7564
+ result = arguments[1];
7565
+ } else {
7566
+ do {
7567
+ if (i in self) {
7568
+ result = self[i--];
7569
+ break;
7570
+ }
7571
+ if (--i < 0) {
7572
+ throw new TypeError("reduceRight of empty array with no initial value");
7573
+ }
7574
+ } while (true);
7575
+ }
7576
+
7577
+ do {
7578
+ if (i in this) {
7579
+ result = fun.call(void 0, result, self[i], i, object);
7580
+ }
7581
+ } while (i--);
7582
+
7583
+ return result;
7584
+ };
7585
+ }
7586
+ if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
7587
+ Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
7588
+ var self = splitString && _toString(this) == "[object String]" ?
7589
+ this.split("") :
7590
+ toObject(this),
7591
+ length = self.length >>> 0;
7592
+
7593
+ if (!length) {
7594
+ return -1;
7595
+ }
7596
+
7597
+ var i = 0;
7598
+ if (arguments.length > 1) {
7599
+ i = toInteger(arguments[1]);
7600
+ }
7601
+ i = i >= 0 ? i : Math.max(0, length + i);
7602
+ for (; i < length; i++) {
7603
+ if (i in self && self[i] === sought) {
7604
+ return i;
7605
+ }
7606
+ }
7607
+ return -1;
7608
+ };
7609
+ }
7610
+ if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
7611
+ Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
7612
+ var self = splitString && _toString(this) == "[object String]" ?
7613
+ this.split("") :
7614
+ toObject(this),
7615
+ length = self.length >>> 0;
7616
+
7617
+ if (!length) {
7618
+ return -1;
7619
+ }
7620
+ var i = length - 1;
7621
+ if (arguments.length > 1) {
7622
+ i = Math.min(i, toInteger(arguments[1]));
7623
+ }
7624
+ i = i >= 0 ? i : length - Math.abs(i);
7625
+ for (; i >= 0; i--) {
7626
+ if (i in self && sought === self[i]) {
7627
+ return i;
7628
+ }
7629
+ }
7630
+ return -1;
7631
+ };
7632
+ }
7633
+ if (!Object.getPrototypeOf) {
7634
+ Object.getPrototypeOf = function getPrototypeOf(object) {
7635
+ return object.__proto__ || (
7636
+ object.constructor ?
7637
+ object.constructor.prototype :
7638
+ prototypeOfObject
7639
+ );
7640
+ };
7641
+ }
7642
+ if (!Object.getOwnPropertyDescriptor) {
7643
+ var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
7644
+ "non-object: ";
7645
+ Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
7646
+ if ((typeof object != "object" && typeof object != "function") || object === null)
7647
+ throw new TypeError(ERR_NON_OBJECT + object);
7648
+ if (!owns(object, property))
7649
+ return;
7650
+
7651
+ var descriptor, getter, setter;
7652
+ descriptor = { enumerable: true, configurable: true };
7653
+ if (supportsAccessors) {
7654
+ var prototype = object.__proto__;
7655
+ object.__proto__ = prototypeOfObject;
7656
+
7657
+ var getter = lookupGetter(object, property);
7658
+ var setter = lookupSetter(object, property);
7659
+ object.__proto__ = prototype;
7660
+
7661
+ if (getter || setter) {
7662
+ if (getter) descriptor.get = getter;
7663
+ if (setter) descriptor.set = setter;
7664
+ return descriptor;
7665
+ }
7666
+ }
7667
+ descriptor.value = object[property];
7668
+ return descriptor;
7669
+ };
7670
+ }
7671
+ if (!Object.getOwnPropertyNames) {
7672
+ Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
7673
+ return Object.keys(object);
7674
+ };
7675
+ }
7676
+ if (!Object.create) {
7677
+ var createEmpty;
7678
+ if (Object.prototype.__proto__ === null) {
7679
+ createEmpty = function () {
7680
+ return { "__proto__": null };
7681
+ };
7682
+ } else {
7683
+ createEmpty = function () {
7684
+ var empty = {};
7685
+ for (var i in empty)
7686
+ empty[i] = null;
7687
+ empty.constructor =
7688
+ empty.hasOwnProperty =
7689
+ empty.propertyIsEnumerable =
7690
+ empty.isPrototypeOf =
7691
+ empty.toLocaleString =
7692
+ empty.toString =
7693
+ empty.valueOf =
7694
+ empty.__proto__ = null;
7695
+ return empty;
7696
+ }
7697
+ }
7698
+
7699
+ Object.create = function create(prototype, properties) {
7700
+ var object;
7701
+ if (prototype === null) {
7702
+ object = createEmpty();
7703
+ } else {
7704
+ if (typeof prototype != "object")
7705
+ throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
7706
+ var Type = function () {};
7707
+ Type.prototype = prototype;
7708
+ object = new Type();
7709
+ object.__proto__ = prototype;
7710
+ }
7711
+ if (properties !== void 0)
7712
+ Object.defineProperties(object, properties);
7713
+ return object;
7714
+ };
7715
+ }
7716
+
7717
+ function doesDefinePropertyWork(object) {
7718
+ try {
7719
+ Object.defineProperty(object, "sentinel", {});
7720
+ return "sentinel" in object;
7721
+ } catch (exception) {
7722
+ }
7723
+ }
7724
+ if (Object.defineProperty) {
7725
+ var definePropertyWorksOnObject = doesDefinePropertyWork({});
7726
+ var definePropertyWorksOnDom = typeof document == "undefined" ||
7727
+ doesDefinePropertyWork(document.createElement("div"));
7728
+ if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
7729
+ var definePropertyFallback = Object.defineProperty;
7730
+ }
7731
+ }
7732
+
7733
+ if (!Object.defineProperty || definePropertyFallback) {
7734
+ var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
7735
+ var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
7736
+ var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
7737
+ "on this javascript engine";
7738
+
7739
+ Object.defineProperty = function defineProperty(object, property, descriptor) {
7740
+ if ((typeof object != "object" && typeof object != "function") || object === null)
7741
+ throw new TypeError(ERR_NON_OBJECT_TARGET + object);
7742
+ if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
7743
+ throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
7744
+ if (definePropertyFallback) {
7745
+ try {
7746
+ return definePropertyFallback.call(Object, object, property, descriptor);
7747
+ } catch (exception) {
7748
+ }
7749
+ }
7750
+ if (owns(descriptor, "value")) {
7751
+
7752
+ if (supportsAccessors && (lookupGetter(object, property) ||
7753
+ lookupSetter(object, property)))
7754
+ {
7755
+ var prototype = object.__proto__;
7756
+ object.__proto__ = prototypeOfObject;
7757
+ delete object[property];
7758
+ object[property] = descriptor.value;
7759
+ object.__proto__ = prototype;
7760
+ } else {
7761
+ object[property] = descriptor.value;
7762
+ }
7763
+ } else {
7764
+ if (!supportsAccessors)
7765
+ throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
7766
+ if (owns(descriptor, "get"))
7767
+ defineGetter(object, property, descriptor.get);
7768
+ if (owns(descriptor, "set"))
7769
+ defineSetter(object, property, descriptor.set);
7770
+ }
7771
+
7772
+ return object;
7773
+ };
7774
+ }
7775
+ if (!Object.defineProperties) {
7776
+ Object.defineProperties = function defineProperties(object, properties) {
7777
+ for (var property in properties) {
7778
+ if (owns(properties, property))
7779
+ Object.defineProperty(object, property, properties[property]);
7780
+ }
7781
+ return object;
7782
+ };
7783
+ }
7784
+ if (!Object.seal) {
7785
+ Object.seal = function seal(object) {
7786
+ return object;
7787
+ };
7788
+ }
7789
+ if (!Object.freeze) {
7790
+ Object.freeze = function freeze(object) {
7791
+ return object;
7792
+ };
7793
+ }
7794
+ try {
7795
+ Object.freeze(function () {});
7796
+ } catch (exception) {
7797
+ Object.freeze = (function freeze(freezeObject) {
7798
+ return function freeze(object) {
7799
+ if (typeof object == "function") {
7800
+ return object;
7801
+ } else {
7802
+ return freezeObject(object);
7803
+ }
7804
+ };
7805
+ })(Object.freeze);
7806
+ }
7807
+ if (!Object.preventExtensions) {
7808
+ Object.preventExtensions = function preventExtensions(object) {
7809
+ return object;
7810
+ };
7811
+ }
7812
+ if (!Object.isSealed) {
7813
+ Object.isSealed = function isSealed(object) {
7814
+ return false;
7815
+ };
7816
+ }
7817
+ if (!Object.isFrozen) {
7818
+ Object.isFrozen = function isFrozen(object) {
7819
+ return false;
7820
+ };
7821
+ }
7822
+ if (!Object.isExtensible) {
7823
+ Object.isExtensible = function isExtensible(object) {
7824
+ if (Object(object) === object) {
7825
+ throw new TypeError(); // TODO message
7826
+ }
7827
+ var name = '';
7828
+ while (owns(object, name)) {
7829
+ name += '?';
7830
+ }
7831
+ object[name] = true;
7832
+ var returnValue = owns(object, name);
7833
+ delete object[name];
7834
+ return returnValue;
7835
+ };
7836
+ }
7837
+ if (!Object.keys) {
7838
+ var hasDontEnumBug = true,
7839
+ dontEnums = [
7840
+ "toString",
7841
+ "toLocaleString",
7842
+ "valueOf",
7843
+ "hasOwnProperty",
7844
+ "isPrototypeOf",
7845
+ "propertyIsEnumerable",
7846
+ "constructor"
7847
+ ],
7848
+ dontEnumsLength = dontEnums.length;
7849
+
7850
+ for (var key in {"toString": null}) {
7851
+ hasDontEnumBug = false;
7852
+ }
7853
+
7854
+ Object.keys = function keys(object) {
7855
+
7856
+ if (
7857
+ (typeof object != "object" && typeof object != "function") ||
7858
+ object === null
7859
+ ) {
7860
+ throw new TypeError("Object.keys called on a non-object");
7861
+ }
7862
+
7863
+ var keys = [];
7864
+ for (var name in object) {
7865
+ if (owns(object, name)) {
7866
+ keys.push(name);
7867
+ }
7868
+ }
7869
+
7870
+ if (hasDontEnumBug) {
7871
+ for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
7872
+ var dontEnum = dontEnums[i];
7873
+ if (owns(object, dontEnum)) {
7874
+ keys.push(dontEnum);
7875
+ }
7876
+ }
7877
+ }
7878
+ return keys;
7879
+ };
7880
+
7881
+ }
7882
+ if (!Date.now) {
7883
+ Date.now = function now() {
7884
+ return new Date().getTime();
7885
+ };
7886
+ }
7887
+ var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
7888
+ "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
7889
+ "\u2029\uFEFF";
7890
+ if (!String.prototype.trim || ws.trim()) {
7891
+ ws = "[" + ws + "]";
7892
+ var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
7893
+ trimEndRegexp = new RegExp(ws + ws + "*$");
7894
+ String.prototype.trim = function trim() {
7895
+ return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
7896
+ };
7897
+ }
7898
+
7899
+ function toInteger(n) {
7900
+ n = +n;
7901
+ if (n !== n) { // isNaN
7902
+ n = 0;
7903
+ } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
7904
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
7905
+ }
7906
+ return n;
7907
+ }
7908
+
7909
+ function isPrimitive(input) {
7910
+ var type = typeof input;
7911
+ return (
7912
+ input === null ||
7913
+ type === "undefined" ||
7914
+ type === "boolean" ||
7915
+ type === "number" ||
7916
+ type === "string"
7917
+ );
7918
+ }
7919
+
7920
+ function toPrimitive(input) {
7921
+ var val, valueOf, toString;
7922
+ if (isPrimitive(input)) {
7923
+ return input;
7924
+ }
7925
+ valueOf = input.valueOf;
7926
+ if (typeof valueOf === "function") {
7927
+ val = valueOf.call(input);
7928
+ if (isPrimitive(val)) {
7929
+ return val;
7930
+ }
7931
+ }
7932
+ toString = input.toString;
7933
+ if (typeof toString === "function") {
7934
+ val = toString.call(input);
7935
+ if (isPrimitive(val)) {
7936
+ return val;
7937
+ }
7938
+ }
7939
+ throw new TypeError();
7940
+ }
7941
+ var toObject = function (o) {
7942
+ if (o == null) { // this matches both null and undefined
7943
+ throw new TypeError("can't convert "+o+" to object");
7944
+ }
7945
+ return Object(o);
7946
+ };
7947
+
7948
+ });
7949
+
7950
+ ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(acequire, exports, module) {
7951
+ "use strict";
7952
+
7953
+ acequire("./regexp");
7954
+ acequire("./es5-shim");
7955
+
7956
+ });
7957
+
7958
+ ace.define("ace/lib/dom",["require","exports","module"], function(acequire, exports, module) {
7959
+ "use strict";
7960
+
7961
+ if (typeof document == "undefined")
7962
+ return;
7963
+
7964
+ var XHTML_NS = "http://www.w3.org/1999/xhtml";
7965
+
7966
+ exports.getDocumentHead = function(doc) {
7967
+ if (!doc)
7968
+ doc = document;
7969
+ return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement;
7970
+ }
7971
+
7972
+ exports.createElement = function(tag, ns) {
7973
+ return document.createElementNS ?
7974
+ document.createElementNS(ns || XHTML_NS, tag) :
7975
+ document.createElement(tag);
7976
+ };
7977
+
7978
+ exports.hasCssClass = function(el, name) {
7979
+ var classes = (el.className || "").split(/\s+/g);
7980
+ return classes.indexOf(name) !== -1;
7981
+ };
7982
+ exports.addCssClass = function(el, name) {
7983
+ if (!exports.hasCssClass(el, name)) {
7984
+ el.className += " " + name;
7985
+ }
7986
+ };
7987
+ exports.removeCssClass = function(el, name) {
7988
+ var classes = el.className.split(/\s+/g);
7989
+ while (true) {
7990
+ var index = classes.indexOf(name);
7991
+ if (index == -1) {
7992
+ break;
7993
+ }
7994
+ classes.splice(index, 1);
7995
+ }
7996
+ el.className = classes.join(" ");
7997
+ };
7998
+
7999
+ exports.toggleCssClass = function(el, name) {
8000
+ var classes = el.className.split(/\s+/g), add = true;
8001
+ while (true) {
8002
+ var index = classes.indexOf(name);
8003
+ if (index == -1) {
8004
+ break;
8005
+ }
8006
+ add = false;
8007
+ classes.splice(index, 1);
8008
+ }
8009
+ if(add)
8010
+ classes.push(name);
8011
+
8012
+ el.className = classes.join(" ");
8013
+ return add;
8014
+ };
8015
+ exports.setCssClass = function(node, className, include) {
8016
+ if (include) {
8017
+ exports.addCssClass(node, className);
8018
+ } else {
8019
+ exports.removeCssClass(node, className);
8020
+ }
8021
+ };
8022
+
8023
+ exports.hasCssString = function(id, doc) {
8024
+ var index = 0, sheets;
8025
+ doc = doc || document;
8026
+
8027
+ if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
8028
+ while (index < sheets.length)
8029
+ if (sheets[index++].owningElement.id === id) return true;
8030
+ } else if ((sheets = doc.getElementsByTagName("style"))) {
8031
+ while (index < sheets.length)
8032
+ if (sheets[index++].id === id) return true;
8033
+ }
8034
+
8035
+ return false;
8036
+ };
8037
+
8038
+ exports.importCssString = function importCssString(cssText, id, doc) {
8039
+ doc = doc || document;
8040
+ if (id && exports.hasCssString(id, doc))
8041
+ return null;
8042
+
8043
+ var style;
8044
+
8045
+ if (doc.createStyleSheet) {
8046
+ style = doc.createStyleSheet();
8047
+ style.cssText = cssText;
8048
+ if (id)
8049
+ style.owningElement.id = id;
8050
+ } else {
8051
+ style = doc.createElementNS
8052
+ ? doc.createElementNS(XHTML_NS, "style")
8053
+ : doc.createElement("style");
8054
+
8055
+ style.appendChild(doc.createTextNode(cssText));
8056
+ if (id)
8057
+ style.id = id;
8058
+
8059
+ exports.getDocumentHead(doc).appendChild(style);
8060
+ }
8061
+ };
8062
+
8063
+ exports.importCssStylsheet = function(uri, doc) {
8064
+ if (doc.createStyleSheet) {
8065
+ doc.createStyleSheet(uri);
8066
+ } else {
8067
+ var link = exports.createElement('link');
8068
+ link.rel = 'stylesheet';
8069
+ link.href = uri;
8070
+
8071
+ exports.getDocumentHead(doc).appendChild(link);
8072
+ }
8073
+ };
8074
+
8075
+ exports.getInnerWidth = function(element) {
8076
+ return (
8077
+ parseInt(exports.computedStyle(element, "paddingLeft"), 10) +
8078
+ parseInt(exports.computedStyle(element, "paddingRight"), 10) +
8079
+ element.clientWidth
8080
+ );
8081
+ };
8082
+
8083
+ exports.getInnerHeight = function(element) {
8084
+ return (
8085
+ parseInt(exports.computedStyle(element, "paddingTop"), 10) +
8086
+ parseInt(exports.computedStyle(element, "paddingBottom"), 10) +
8087
+ element.clientHeight
8088
+ );
8089
+ };
8090
+
8091
+ if (window.pageYOffset !== undefined) {
8092
+ exports.getPageScrollTop = function() {
8093
+ return window.pageYOffset;
8094
+ };
8095
+
8096
+ exports.getPageScrollLeft = function() {
8097
+ return window.pageXOffset;
8098
+ };
8099
+ }
8100
+ else {
8101
+ exports.getPageScrollTop = function() {
8102
+ return document.body.scrollTop;
8103
+ };
8104
+
8105
+ exports.getPageScrollLeft = function() {
8106
+ return document.body.scrollLeft;
8107
+ };
8108
+ }
8109
+
8110
+ if (window.getComputedStyle)
8111
+ exports.computedStyle = function(element, style) {
8112
+ if (style)
8113
+ return (window.getComputedStyle(element, "") || {})[style] || "";
8114
+ return window.getComputedStyle(element, "") || {};
8115
+ };
8116
+ else
8117
+ exports.computedStyle = function(element, style) {
8118
+ if (style)
8119
+ return element.currentStyle[style];
8120
+ return element.currentStyle;
8121
+ };
8122
+
8123
+ exports.scrollbarWidth = function(document) {
8124
+ var inner = exports.createElement("ace_inner");
8125
+ inner.style.width = "100%";
8126
+ inner.style.minWidth = "0px";
8127
+ inner.style.height = "200px";
8128
+ inner.style.display = "block";
8129
+
8130
+ var outer = exports.createElement("ace_outer");
8131
+ var style = outer.style;
8132
+
8133
+ style.position = "absolute";
8134
+ style.left = "-10000px";
8135
+ style.overflow = "hidden";
8136
+ style.width = "200px";
8137
+ style.minWidth = "0px";
8138
+ style.height = "150px";
8139
+ style.display = "block";
8140
+
8141
+ outer.appendChild(inner);
8142
+
8143
+ var body = document.documentElement;
8144
+ body.appendChild(outer);
8145
+
8146
+ var noScrollbar = inner.offsetWidth;
8147
+
8148
+ style.overflow = "scroll";
8149
+ var withScrollbar = inner.offsetWidth;
8150
+
8151
+ if (noScrollbar == withScrollbar) {
8152
+ withScrollbar = outer.clientWidth;
8153
+ }
8154
+
8155
+ body.removeChild(outer);
8156
+
8157
+ return noScrollbar-withScrollbar;
8158
+ };
8159
+ exports.setInnerHtml = function(el, innerHtml) {
8160
+ var element = el.cloneNode(false);//document.createElement("div");
8161
+ element.innerHTML = innerHtml;
8162
+ el.parentNode.replaceChild(element, el);
8163
+ return element;
8164
+ };
8165
+
8166
+ if ("textContent" in document.documentElement) {
8167
+ exports.setInnerText = function(el, innerText) {
8168
+ el.textContent = innerText;
8169
+ };
8170
+
8171
+ exports.getInnerText = function(el) {
8172
+ return el.textContent;
8173
+ };
8174
+ }
8175
+ else {
8176
+ exports.setInnerText = function(el, innerText) {
8177
+ el.innerText = innerText;
8178
+ };
8179
+
8180
+ exports.getInnerText = function(el) {
8181
+ return el.innerText;
8182
+ };
8183
+ }
8184
+
8185
+ exports.getParentWindow = function(document) {
8186
+ return document.defaultView || document.parentWindow;
8187
+ };
8188
+
8189
+ });
8190
+
8191
+ ace.define("ace/lib/oop",["require","exports","module"], function(acequire, exports, module) {
8192
+ "use strict";
8193
+
8194
+ exports.inherits = function(ctor, superCtor) {
8195
+ ctor.super_ = superCtor;
8196
+ ctor.prototype = Object.create(superCtor.prototype, {
8197
+ constructor: {
8198
+ value: ctor,
8199
+ enumerable: false,
8200
+ writable: true,
8201
+ configurable: true
8202
+ }
8203
+ });
8204
+ };
8205
+
8206
+ exports.mixin = function(obj, mixin) {
8207
+ for (var key in mixin) {
8208
+ obj[key] = mixin[key];
8209
+ }
8210
+ return obj;
8211
+ };
8212
+
8213
+ exports.implement = function(proto, mixin) {
8214
+ exports.mixin(proto, mixin);
8215
+ };
8216
+
8217
+ });
8218
+
8219
+ ace.define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(acequire, exports, module) {
8220
+ "use strict";
8221
+
8222
+ acequire("./fixoldbrowsers");
8223
+
8224
+ var oop = acequire("./oop");
8225
+ var Keys = (function() {
8226
+ var ret = {
8227
+ MODIFIER_KEYS: {
8228
+ 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'
8229
+ },
8230
+
8231
+ KEY_MODS: {
8232
+ "ctrl": 1, "alt": 2, "option" : 2, "shift": 4,
8233
+ "super": 8, "meta": 8, "command": 8, "cmd": 8
8234
+ },
8235
+
8236
+ FUNCTION_KEYS : {
8237
+ 8 : "Backspace",
8238
+ 9 : "Tab",
8239
+ 13 : "Return",
8240
+ 19 : "Pause",
8241
+ 27 : "Esc",
8242
+ 32 : "Space",
8243
+ 33 : "PageUp",
8244
+ 34 : "PageDown",
8245
+ 35 : "End",
8246
+ 36 : "Home",
8247
+ 37 : "Left",
8248
+ 38 : "Up",
8249
+ 39 : "Right",
8250
+ 40 : "Down",
8251
+ 44 : "Print",
8252
+ 45 : "Insert",
8253
+ 46 : "Delete",
8254
+ 96 : "Numpad0",
8255
+ 97 : "Numpad1",
8256
+ 98 : "Numpad2",
8257
+ 99 : "Numpad3",
8258
+ 100: "Numpad4",
8259
+ 101: "Numpad5",
8260
+ 102: "Numpad6",
8261
+ 103: "Numpad7",
8262
+ 104: "Numpad8",
8263
+ 105: "Numpad9",
8264
+ '-13': "NumpadEnter",
8265
+ 112: "F1",
8266
+ 113: "F2",
8267
+ 114: "F3",
8268
+ 115: "F4",
8269
+ 116: "F5",
8270
+ 117: "F6",
8271
+ 118: "F7",
8272
+ 119: "F8",
8273
+ 120: "F9",
8274
+ 121: "F10",
8275
+ 122: "F11",
8276
+ 123: "F12",
8277
+ 144: "Numlock",
8278
+ 145: "Scrolllock"
8279
+ },
8280
+
8281
+ PRINTABLE_KEYS: {
8282
+ 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5',
8283
+ 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a',
8284
+ 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h',
8285
+ 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o',
8286
+ 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',
8287
+ 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',
8288
+ 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[',
8289
+ 220: '\\',221: ']', 222: '\''
8290
+ }
8291
+ };
8292
+ var name, i;
8293
+ for (i in ret.FUNCTION_KEYS) {
8294
+ name = ret.FUNCTION_KEYS[i].toLowerCase();
8295
+ ret[name] = parseInt(i, 10);
8296
+ }
8297
+ for (i in ret.PRINTABLE_KEYS) {
8298
+ name = ret.PRINTABLE_KEYS[i].toLowerCase();
8299
+ ret[name] = parseInt(i, 10);
8300
+ }
8301
+ oop.mixin(ret, ret.MODIFIER_KEYS);
8302
+ oop.mixin(ret, ret.PRINTABLE_KEYS);
8303
+ oop.mixin(ret, ret.FUNCTION_KEYS);
8304
+ ret.enter = ret["return"];
8305
+ ret.escape = ret.esc;
8306
+ ret.del = ret["delete"];
8307
+ ret[173] = '-';
8308
+
8309
+ (function() {
8310
+ var mods = ["cmd", "ctrl", "alt", "shift"];
8311
+ for (var i = Math.pow(2, mods.length); i--;) {
8312
+ ret.KEY_MODS[i] = mods.filter(function(x) {
8313
+ return i & ret.KEY_MODS[x];
8314
+ }).join("-") + "-";
8315
+ }
8316
+ })();
8317
+
8318
+ ret.KEY_MODS[0] = "";
8319
+ ret.KEY_MODS[-1] = "input";
8320
+
8321
+ return ret;
8322
+ })();
8323
+ oop.mixin(exports, Keys);
8324
+
8325
+ exports.keyCodeToString = function(keyCode) {
8326
+ var keyString = Keys[keyCode];
8327
+ if (typeof keyString != "string")
8328
+ keyString = String.fromCharCode(keyCode);
8329
+ return keyString.toLowerCase();
8330
+ };
8331
+
8332
+ });
8333
+
8334
+ ace.define("ace/lib/useragent",["require","exports","module"], function(acequire, exports, module) {
8335
+ "use strict";
8336
+ exports.OS = {
8337
+ LINUX: "LINUX",
8338
+ MAC: "MAC",
8339
+ WINDOWS: "WINDOWS"
8340
+ };
8341
+ exports.getOS = function() {
8342
+ if (exports.isMac) {
8343
+ return exports.OS.MAC;
8344
+ } else if (exports.isLinux) {
8345
+ return exports.OS.LINUX;
8346
+ } else {
8347
+ return exports.OS.WINDOWS;
8348
+ }
8349
+ };
8350
+ if (typeof navigator != "object")
8351
+ return;
8352
+
8353
+ var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase();
8354
+ var ua = navigator.userAgent;
8355
+ exports.isWin = (os == "win");
8356
+ exports.isMac = (os == "mac");
8357
+ exports.isLinux = (os == "linux");
8358
+ exports.isIE =
8359
+ (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0)
8360
+ ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1])
8361
+ : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie
8362
+
8363
+ exports.isOldIE = exports.isIE && exports.isIE < 9;
8364
+ exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko";
8365
+ exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\:(\d+)/)||[])[1], 10) < 4;
8366
+ exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";
8367
+ exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined;
8368
+
8369
+ exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined;
8370
+
8371
+ exports.isAIR = ua.indexOf("AdobeAIR") >= 0;
8372
+
8373
+ exports.isIPad = ua.indexOf("iPad") >= 0;
8374
+
8375
+ exports.isTouchPad = ua.indexOf("TouchPad") >= 0;
8376
+
8377
+ exports.isChromeOS = ua.indexOf(" CrOS ") >= 0;
8378
+
8379
+ });
8380
+
8381
+ ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) {
8382
+ "use strict";
8383
+
8384
+ var keys = acequire("./keys");
8385
+ var useragent = acequire("./useragent");
8386
+
8387
+ exports.addListener = function(elem, type, callback) {
8388
+ if (elem.addEventListener) {
8389
+ return elem.addEventListener(type, callback, false);
8390
+ }
8391
+ if (elem.attachEvent) {
8392
+ var wrapper = function() {
8393
+ callback.call(elem, window.event);
8394
+ };
8395
+ callback._wrapper = wrapper;
8396
+ elem.attachEvent("on" + type, wrapper);
8397
+ }
8398
+ };
8399
+
8400
+ exports.removeListener = function(elem, type, callback) {
8401
+ if (elem.removeEventListener) {
8402
+ return elem.removeEventListener(type, callback, false);
8403
+ }
8404
+ if (elem.detachEvent) {
8405
+ elem.detachEvent("on" + type, callback._wrapper || callback);
8406
+ }
8407
+ };
8408
+ exports.stopEvent = function(e) {
8409
+ exports.stopPropagation(e);
8410
+ exports.preventDefault(e);
8411
+ return false;
8412
+ };
8413
+
8414
+ exports.stopPropagation = function(e) {
8415
+ if (e.stopPropagation)
8416
+ e.stopPropagation();
8417
+ else
8418
+ e.cancelBubble = true;
8419
+ };
8420
+
8421
+ exports.preventDefault = function(e) {
8422
+ if (e.preventDefault)
8423
+ e.preventDefault();
8424
+ else
8425
+ e.returnValue = false;
8426
+ };
8427
+ exports.getButton = function(e) {
8428
+ if (e.type == "dblclick")
8429
+ return 0;
8430
+ if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey)))
8431
+ return 2;
8432
+ if (e.preventDefault) {
8433
+ return e.button;
8434
+ }
8435
+ else {
8436
+ return {1:0, 2:2, 4:1}[e.button];
8437
+ }
8438
+ };
8439
+
8440
+ exports.capture = function(el, eventHandler, releaseCaptureHandler) {
8441
+ function onMouseUp(e) {
8442
+ eventHandler && eventHandler(e);
8443
+ releaseCaptureHandler && releaseCaptureHandler(e);
8444
+
8445
+ exports.removeListener(document, "mousemove", eventHandler, true);
8446
+ exports.removeListener(document, "mouseup", onMouseUp, true);
8447
+ exports.removeListener(document, "dragstart", onMouseUp, true);
8448
+ }
8449
+
8450
+ exports.addListener(document, "mousemove", eventHandler, true);
8451
+ exports.addListener(document, "mouseup", onMouseUp, true);
8452
+ exports.addListener(document, "dragstart", onMouseUp, true);
8453
+
8454
+ return onMouseUp;
8455
+ };
8456
+
8457
+ exports.addMouseWheelListener = function(el, callback) {
8458
+ if ("onmousewheel" in el) {
8459
+ exports.addListener(el, "mousewheel", function(e) {
8460
+ var factor = 8;
8461
+ if (e.wheelDeltaX !== undefined) {
8462
+ e.wheelX = -e.wheelDeltaX / factor;
8463
+ e.wheelY = -e.wheelDeltaY / factor;
8464
+ } else {
8465
+ e.wheelX = 0;
8466
+ e.wheelY = -e.wheelDelta / factor;
8467
+ }
8468
+ callback(e);
8469
+ });
8470
+ } else if ("onwheel" in el) {
8471
+ exports.addListener(el, "wheel", function(e) {
8472
+ var factor = 0.35;
8473
+ switch (e.deltaMode) {
8474
+ case e.DOM_DELTA_PIXEL:
8475
+ e.wheelX = e.deltaX * factor || 0;
8476
+ e.wheelY = e.deltaY * factor || 0;
8477
+ break;
8478
+ case e.DOM_DELTA_LINE:
8479
+ case e.DOM_DELTA_PAGE:
8480
+ e.wheelX = (e.deltaX || 0) * 5;
8481
+ e.wheelY = (e.deltaY || 0) * 5;
8482
+ break;
8483
+ }
8484
+
8485
+ callback(e);
8486
+ });
8487
+ } else {
8488
+ exports.addListener(el, "DOMMouseScroll", function(e) {
8489
+ if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
8490
+ e.wheelX = (e.detail || 0) * 5;
8491
+ e.wheelY = 0;
8492
+ } else {
8493
+ e.wheelX = 0;
8494
+ e.wheelY = (e.detail || 0) * 5;
8495
+ }
8496
+ callback(e);
8497
+ });
8498
+ }
8499
+ };
8500
+
8501
+ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) {
8502
+ var clicks = 0;
8503
+ var startX, startY, timer;
8504
+ var eventNames = {
8505
+ 2: "dblclick",
8506
+ 3: "tripleclick",
8507
+ 4: "quadclick"
8508
+ };
8509
+
8510
+ exports.addListener(el, "mousedown", function(e) {
8511
+ if (exports.getButton(e) !== 0) {
8512
+ clicks = 0;
8513
+ } else if (e.detail > 1) {
8514
+ clicks++;
8515
+ if (clicks > 4)
8516
+ clicks = 1;
8517
+ } else {
8518
+ clicks = 1;
8519
+ }
8520
+ if (useragent.isIE) {
8521
+ var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5;
8522
+ if (!timer || isNewClick)
8523
+ clicks = 1;
8524
+ if (timer)
8525
+ clearTimeout(timer);
8526
+ timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
8527
+
8528
+ if (clicks == 1) {
8529
+ startX = e.clientX;
8530
+ startY = e.clientY;
8531
+ }
8532
+ }
8533
+
8534
+ e._clicks = clicks;
8535
+
8536
+ eventHandler[callbackName]("mousedown", e);
8537
+
8538
+ if (clicks > 4)
8539
+ clicks = 0;
8540
+ else if (clicks > 1)
8541
+ return eventHandler[callbackName](eventNames[clicks], e);
8542
+ });
8543
+
8544
+ if (useragent.isOldIE) {
8545
+ exports.addListener(el, "dblclick", function(e) {
8546
+ clicks = 2;
8547
+ if (timer)
8548
+ clearTimeout(timer);
8549
+ timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
8550
+ eventHandler[callbackName]("mousedown", e);
8551
+ eventHandler[callbackName](eventNames[clicks], e);
8552
+ });
8553
+ }
8554
+ };
8555
+
8556
+ var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window)
8557
+ ? function(e) {
8558
+ return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
8559
+ }
8560
+ : function(e) {
8561
+ return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
8562
+ };
8563
+
8564
+ exports.getModifierString = function(e) {
8565
+ return keys.KEY_MODS[getModifierHash(e)];
8566
+ };
8567
+
8568
+ function normalizeCommandKeys(callback, e, keyCode) {
8569
+ var hashId = getModifierHash(e);
8570
+
8571
+ if (!useragent.isMac && pressedKeys) {
8572
+ if (pressedKeys[91] || pressedKeys[92])
8573
+ hashId |= 8;
8574
+ if (pressedKeys.altGr) {
8575
+ if ((3 & hashId) != 3)
8576
+ pressedKeys.altGr = 0;
8577
+ else
8578
+ return;
8579
+ }
8580
+ if (keyCode === 18 || keyCode === 17) {
8581
+ var location = "location" in e ? e.location : e.keyLocation;
8582
+ if (keyCode === 17 && location === 1) {
8583
+ ts = e.timeStamp;
8584
+ } else if (keyCode === 18 && hashId === 3 && location === 2) {
8585
+ var dt = -ts;
8586
+ ts = e.timeStamp;
8587
+ dt += ts;
8588
+ if (dt < 3)
8589
+ pressedKeys.altGr = true;
8590
+ }
8591
+ }
8592
+ }
8593
+
8594
+ if (keyCode in keys.MODIFIER_KEYS) {
8595
+ switch (keys.MODIFIER_KEYS[keyCode]) {
8596
+ case "Alt":
8597
+ hashId = 2;
8598
+ break;
8599
+ case "Shift":
8600
+ hashId = 4;
8601
+ break;
8602
+ case "Ctrl":
8603
+ hashId = 1;
8604
+ break;
8605
+ default:
8606
+ hashId = 8;
8607
+ break;
8608
+ }
8609
+ keyCode = -1;
8610
+ }
8611
+
8612
+ if (hashId & 8 && (keyCode === 91 || keyCode === 93)) {
8613
+ keyCode = -1;
8614
+ }
8615
+
8616
+ if (!hashId && keyCode === 13) {
8617
+ var location = "location" in e ? e.location : e.keyLocation;
8618
+ if (location === 3) {
8619
+ callback(e, hashId, -keyCode);
8620
+ if (e.defaultPrevented)
8621
+ return;
8622
+ }
8623
+ }
8624
+
8625
+ if (useragent.isChromeOS && hashId & 8) {
8626
+ callback(e, hashId, keyCode);
8627
+ if (e.defaultPrevented)
8628
+ return;
8629
+ else
8630
+ hashId &= ~8;
8631
+ }
8632
+ if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {
8633
+ return false;
8634
+ }
8635
+
8636
+ return callback(e, hashId, keyCode);
8637
+ }
8638
+
8639
+ var pressedKeys = null;
8640
+ var ts = 0;
8641
+ exports.addCommandKeyListener = function(el, callback) {
8642
+ var addListener = exports.addListener;
8643
+ if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
8644
+ var lastKeyDownKeyCode = null;
8645
+ addListener(el, "keydown", function(e) {
8646
+ lastKeyDownKeyCode = e.keyCode;
8647
+ });
8648
+ addListener(el, "keypress", function(e) {
8649
+ return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);
8650
+ });
8651
+ } else {
8652
+ var lastDefaultPrevented = null;
8653
+
8654
+ addListener(el, "keydown", function(e) {
8655
+ pressedKeys[e.keyCode] = true;
8656
+ var result = normalizeCommandKeys(callback, e, e.keyCode);
8657
+ lastDefaultPrevented = e.defaultPrevented;
8658
+ return result;
8659
+ });
8660
+
8661
+ addListener(el, "keypress", function(e) {
8662
+ if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) {
8663
+ exports.stopEvent(e);
8664
+ lastDefaultPrevented = null;
8665
+ }
8666
+ });
8667
+
8668
+ addListener(el, "keyup", function(e) {
8669
+ pressedKeys[e.keyCode] = null;
8670
+ });
8671
+
8672
+ if (!pressedKeys) {
8673
+ pressedKeys = Object.create(null);
8674
+ addListener(window, "focus", function(e) {
8675
+ pressedKeys = Object.create(null);
8676
+ });
8677
+ }
8678
+ }
8679
+ };
8680
+
8681
+ if (window.postMessage && !useragent.isOldIE) {
8682
+ var postMessageId = 1;
8683
+ exports.nextTick = function(callback, win) {
8684
+ win = win || window;
8685
+ var messageName = "zero-timeout-message-" + postMessageId;
8686
+ exports.addListener(win, "message", function listener(e) {
8687
+ if (e.data == messageName) {
8688
+ exports.stopPropagation(e);
8689
+ exports.removeListener(win, "message", listener);
8690
+ callback();
8691
+ }
8692
+ });
8693
+ win.postMessage(messageName, "*");
8694
+ };
8695
+ }
8696
+
8697
+
8698
+ exports.nextFrame = window.requestAnimationFrame ||
8699
+ window.mozRequestAnimationFrame ||
8700
+ window.webkitRequestAnimationFrame ||
8701
+ window.msRequestAnimationFrame ||
8702
+ window.oRequestAnimationFrame;
8703
+
8704
+ if (exports.nextFrame)
8705
+ exports.nextFrame = exports.nextFrame.bind(window);
8706
+ else
8707
+ exports.nextFrame = function(callback) {
8708
+ setTimeout(callback, 17);
8709
+ };
8710
+ });
8711
+
8712
+ ace.define("ace/lib/lang",["require","exports","module"], function(acequire, exports, module) {
8713
+ "use strict";
8714
+
8715
+ exports.last = function(a) {
8716
+ return a[a.length - 1];
8717
+ };
8718
+
8719
+ exports.stringReverse = function(string) {
8720
+ return string.split("").reverse().join("");
8721
+ };
8722
+
8723
+ exports.stringRepeat = function (string, count) {
8724
+ var result = '';
8725
+ while (count > 0) {
8726
+ if (count & 1)
8727
+ result += string;
8728
+
8729
+ if (count >>= 1)
8730
+ string += string;
8731
+ }
8732
+ return result;
8733
+ };
8734
+
8735
+ var trimBeginRegexp = /^\s\s*/;
8736
+ var trimEndRegexp = /\s\s*$/;
8737
+
8738
+ exports.stringTrimLeft = function (string) {
8739
+ return string.replace(trimBeginRegexp, '');
8740
+ };
8741
+
8742
+ exports.stringTrimRight = function (string) {
8743
+ return string.replace(trimEndRegexp, '');
8744
+ };
8745
+
8746
+ exports.copyObject = function(obj) {
8747
+ var copy = {};
8748
+ for (var key in obj) {
8749
+ copy[key] = obj[key];
8750
+ }
8751
+ return copy;
8752
+ };
8753
+
8754
+ exports.copyArray = function(array){
8755
+ var copy = [];
8756
+ for (var i=0, l=array.length; i<l; i++) {
8757
+ if (array[i] && typeof array[i] == "object")
8758
+ copy[i] = this.copyObject( array[i] );
8759
+ else
8760
+ copy[i] = array[i];
8761
+ }
8762
+ return copy;
8763
+ };
8764
+
8765
+ exports.deepCopy = function (obj) {
8766
+ if (typeof obj !== "object" || !obj)
8767
+ return obj;
8768
+ var cons = obj.constructor;
8769
+ if (cons === RegExp)
8770
+ return obj;
8771
+
8772
+ var copy = cons();
8773
+ for (var key in obj) {
8774
+ if (typeof obj[key] === "object") {
8775
+ copy[key] = exports.deepCopy(obj[key]);
8776
+ } else {
8777
+ copy[key] = obj[key];
8778
+ }
8779
+ }
8780
+ return copy;
8781
+ };
8782
+
8783
+ exports.arrayToMap = function(arr) {
8784
+ var map = {};
8785
+ for (var i=0; i<arr.length; i++) {
8786
+ map[arr[i]] = 1;
8787
+ }
8788
+ return map;
8789
+
8790
+ };
8791
+
8792
+ exports.createMap = function(props) {
8793
+ var map = Object.create(null);
8794
+ for (var i in props) {
8795
+ map[i] = props[i];
8796
+ }
8797
+ return map;
8798
+ };
8799
+ exports.arrayRemove = function(array, value) {
8800
+ for (var i = 0; i <= array.length; i++) {
8801
+ if (value === array[i]) {
8802
+ array.splice(i, 1);
8803
+ }
8804
+ }
8805
+ };
8806
+
8807
+ exports.escapeRegExp = function(str) {
8808
+ return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
8809
+ };
8810
+
8811
+ exports.escapeHTML = function(str) {
8812
+ return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
8813
+ };
8814
+
8815
+ exports.getMatchOffsets = function(string, regExp) {
8816
+ var matches = [];
8817
+
8818
+ string.replace(regExp, function(str) {
8819
+ matches.push({
8820
+ offset: arguments[arguments.length-2],
8821
+ length: str.length
8822
+ });
8823
+ });
8824
+
8825
+ return matches;
8826
+ };
8827
+ exports.deferredCall = function(fcn) {
8828
+ var timer = null;
8829
+ var callback = function() {
8830
+ timer = null;
8831
+ fcn();
8832
+ };
8833
+
8834
+ var deferred = function(timeout) {
8835
+ deferred.cancel();
8836
+ timer = setTimeout(callback, timeout || 0);
8837
+ return deferred;
8838
+ };
8839
+
8840
+ deferred.schedule = deferred;
8841
+
8842
+ deferred.call = function() {
8843
+ this.cancel();
8844
+ fcn();
8845
+ return deferred;
8846
+ };
8847
+
8848
+ deferred.cancel = function() {
8849
+ clearTimeout(timer);
8850
+ timer = null;
8851
+ return deferred;
8852
+ };
8853
+
8854
+ deferred.isPending = function() {
8855
+ return timer;
8856
+ };
8857
+
8858
+ return deferred;
8859
+ };
8860
+
8861
+
8862
+ exports.delayedCall = function(fcn, defaultTimeout) {
8863
+ var timer = null;
8864
+ var callback = function() {
8865
+ timer = null;
8866
+ fcn();
8867
+ };
8868
+
8869
+ var _self = function(timeout) {
8870
+ if (timer == null)
8871
+ timer = setTimeout(callback, timeout || defaultTimeout);
8872
+ };
8873
+
8874
+ _self.delay = function(timeout) {
8875
+ timer && clearTimeout(timer);
8876
+ timer = setTimeout(callback, timeout || defaultTimeout);
8877
+ };
8878
+ _self.schedule = _self;
8879
+
8880
+ _self.call = function() {
8881
+ this.cancel();
8882
+ fcn();
8883
+ };
8884
+
8885
+ _self.cancel = function() {
8886
+ timer && clearTimeout(timer);
8887
+ timer = null;
8888
+ };
8889
+
8890
+ _self.isPending = function() {
8891
+ return timer;
8892
+ };
8893
+
8894
+ return _self;
8895
+ };
8896
+ });
8897
+
8898
+ ace.define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang"], function(acequire, exports, module) {
8899
+ "use strict";
8900
+
8901
+ var event = acequire("../lib/event");
8902
+ var useragent = acequire("../lib/useragent");
8903
+ var dom = acequire("../lib/dom");
8904
+ var lang = acequire("../lib/lang");
8905
+ var BROKEN_SETDATA = useragent.isChrome < 18;
8906
+ var USE_IE_MIME_TYPE = useragent.isIE;
8907
+
8908
+ var TextInput = function(parentNode, host) {
8909
+ var text = dom.createElement("textarea");
8910
+ text.className = "ace_text-input";
8911
+
8912
+ if (useragent.isTouchPad)
8913
+ text.setAttribute("x-palm-disable-auto-cap", true);
8914
+
8915
+ text.wrap = "off";
8916
+ text.autocorrect = "off";
8917
+ text.autocapitalize = "off";
8918
+ text.spellcheck = false;
8919
+
8920
+ text.style.opacity = "0";
8921
+ if (useragent.isOldIE) text.style.top = "-100px";
8922
+ parentNode.insertBefore(text, parentNode.firstChild);
8923
+
8924
+ var PLACEHOLDER = "\x01\x01";
8925
+
8926
+ var copied = false;
8927
+ var pasted = false;
8928
+ var inComposition = false;
8929
+ var tempStyle = '';
8930
+ var isSelectionEmpty = true;
8931
+ try { var isFocused = document.activeElement === text; } catch(e) {}
8932
+
8933
+ event.addListener(text, "blur", function(e) {
8934
+ host.onBlur(e);
8935
+ isFocused = false;
8936
+ });
8937
+ event.addListener(text, "focus", function(e) {
8938
+ isFocused = true;
8939
+ host.onFocus(e);
8940
+ resetSelection();
8941
+ });
8942
+ this.focus = function() { text.focus(); };
8943
+ this.blur = function() { text.blur(); };
8944
+ this.isFocused = function() {
8945
+ return isFocused;
8946
+ };
8947
+ var syncSelection = lang.delayedCall(function() {
8948
+ isFocused && resetSelection(isSelectionEmpty);
8949
+ });
8950
+ var syncValue = lang.delayedCall(function() {
8951
+ if (!inComposition) {
8952
+ text.value = PLACEHOLDER;
8953
+ isFocused && resetSelection();
8954
+ }
8955
+ });
8956
+
8957
+ function resetSelection(isEmpty) {
8958
+ if (inComposition)
8959
+ return;
8960
+ if (inputHandler) {
8961
+ selectionStart = 0;
8962
+ selectionEnd = isEmpty ? 0 : text.value.length - 1;
8963
+ } else {
8964
+ var selectionStart = isEmpty ? 2 : 1;
8965
+ var selectionEnd = 2;
8966
+ }
8967
+ try {
8968
+ text.setSelectionRange(selectionStart, selectionEnd);
8969
+ } catch(e){}
8970
+ }
8971
+
8972
+ function resetValue() {
8973
+ if (inComposition)
8974
+ return;
8975
+ text.value = PLACEHOLDER;
8976
+ if (useragent.isWebKit)
8977
+ syncValue.schedule();
8978
+ }
8979
+
8980
+ useragent.isWebKit || host.addEventListener('changeSelection', function() {
8981
+ if (host.selection.isEmpty() != isSelectionEmpty) {
8982
+ isSelectionEmpty = !isSelectionEmpty;
8983
+ syncSelection.schedule();
8984
+ }
8985
+ });
8986
+
8987
+ resetValue();
8988
+ if (isFocused)
8989
+ host.onFocus();
8990
+
8991
+
8992
+ var isAllSelected = function(text) {
8993
+ return text.selectionStart === 0 && text.selectionEnd === text.value.length;
8994
+ };
8995
+ if (!text.setSelectionRange && text.createTextRange) {
8996
+ text.setSelectionRange = function(selectionStart, selectionEnd) {
8997
+ var range = this.createTextRange();
8998
+ range.collapse(true);
8999
+ range.moveStart('character', selectionStart);
9000
+ range.moveEnd('character', selectionEnd);
9001
+ range.select();
9002
+ };
9003
+ isAllSelected = function(text) {
9004
+ try {
9005
+ var range = text.ownerDocument.selection.createRange();
9006
+ }catch(e) {}
9007
+ if (!range || range.parentElement() != text) return false;
9008
+ return range.text == text.value;
9009
+ }
9010
+ }
9011
+ if (useragent.isOldIE) {
9012
+ var inPropertyChange = false;
9013
+ var onPropertyChange = function(e){
9014
+ if (inPropertyChange)
9015
+ return;
9016
+ var data = text.value;
9017
+ if (inComposition || !data || data == PLACEHOLDER)
9018
+ return;
9019
+ if (e && data == PLACEHOLDER[0])
9020
+ return syncProperty.schedule();
9021
+
9022
+ sendText(data);
9023
+ inPropertyChange = true;
9024
+ resetValue();
9025
+ inPropertyChange = false;
9026
+ };
9027
+ var syncProperty = lang.delayedCall(onPropertyChange);
9028
+ event.addListener(text, "propertychange", onPropertyChange);
9029
+
9030
+ var keytable = { 13:1, 27:1 };
9031
+ event.addListener(text, "keyup", function (e) {
9032
+ if (inComposition && (!text.value || keytable[e.keyCode]))
9033
+ setTimeout(onCompositionEnd, 0);
9034
+ if ((text.value.charCodeAt(0)||0) < 129) {
9035
+ return syncProperty.call();
9036
+ }
9037
+ inComposition ? onCompositionUpdate() : onCompositionStart();
9038
+ });
9039
+ event.addListener(text, "keydown", function (e) {
9040
+ syncProperty.schedule(50);
9041
+ });
9042
+ }
9043
+
9044
+ var onSelect = function(e) {
9045
+ if (copied) {
9046
+ copied = false;
9047
+ } else if (isAllSelected(text)) {
9048
+ host.selectAll();
9049
+ resetSelection();
9050
+ } else if (inputHandler) {
9051
+ resetSelection(host.selection.isEmpty());
9052
+ }
9053
+ };
9054
+
9055
+ var inputHandler = null;
9056
+ this.setInputHandler = function(cb) {inputHandler = cb};
9057
+ this.getInputHandler = function() {return inputHandler};
9058
+ var afterContextMenu = false;
9059
+
9060
+ var sendText = function(data) {
9061
+ if (inputHandler) {
9062
+ data = inputHandler(data);
9063
+ inputHandler = null;
9064
+ }
9065
+ if (pasted) {
9066
+ resetSelection();
9067
+ if (data)
9068
+ host.onPaste(data);
9069
+ pasted = false;
9070
+ } else if (data == PLACEHOLDER.charAt(0)) {
9071
+ if (afterContextMenu)
9072
+ host.execCommand("del", {source: "ace"});
9073
+ else // some versions of android do not fire keydown when pressing backspace
9074
+ host.execCommand("backspace", {source: "ace"});
9075
+ } else {
9076
+ if (data.substring(0, 2) == PLACEHOLDER)
9077
+ data = data.substr(2);
9078
+ else if (data.charAt(0) == PLACEHOLDER.charAt(0))
9079
+ data = data.substr(1);
9080
+ else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
9081
+ data = data.slice(0, -1);
9082
+ if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
9083
+ data = data.slice(0, -1);
9084
+
9085
+ if (data)
9086
+ host.onTextInput(data);
9087
+ }
9088
+ if (afterContextMenu)
9089
+ afterContextMenu = false;
9090
+ };
9091
+ var onInput = function(e) {
9092
+ if (inComposition)
9093
+ return;
9094
+ var data = text.value;
9095
+ sendText(data);
9096
+ resetValue();
9097
+ };
9098
+
9099
+ var handleClipboardData = function(e, data) {
9100
+ var clipboardData = e.clipboardData || window.clipboardData;
9101
+ if (!clipboardData || BROKEN_SETDATA)
9102
+ return;
9103
+ var mime = USE_IE_MIME_TYPE ? "Text" : "text/plain";
9104
+ if (data) {
9105
+ return clipboardData.setData(mime, data) !== false;
9106
+ } else {
9107
+ return clipboardData.getData(mime);
9108
+ }
9109
+ };
9110
+
9111
+ var doCopy = function(e, isCut) {
9112
+ var data = host.getCopyText();
9113
+ if (!data)
9114
+ return event.preventDefault(e);
9115
+
9116
+ if (handleClipboardData(e, data)) {
9117
+ isCut ? host.onCut() : host.onCopy();
9118
+ event.preventDefault(e);
9119
+ } else {
9120
+ copied = true;
9121
+ text.value = data;
9122
+ text.select();
9123
+ setTimeout(function(){
9124
+ copied = false;
9125
+ resetValue();
9126
+ resetSelection();
9127
+ isCut ? host.onCut() : host.onCopy();
9128
+ });
9129
+ }
9130
+ };
9131
+
9132
+ var onCut = function(e) {
9133
+ doCopy(e, true);
9134
+ };
9135
+
9136
+ var onCopy = function(e) {
9137
+ doCopy(e, false);
9138
+ };
9139
+
9140
+ var onPaste = function(e) {
9141
+ var data = handleClipboardData(e);
9142
+ if (typeof data == "string") {
9143
+ if (data)
9144
+ host.onPaste(data);
9145
+ if (useragent.isIE)
9146
+ setTimeout(resetSelection);
9147
+ event.preventDefault(e);
9148
+ }
9149
+ else {
9150
+ text.value = "";
9151
+ pasted = true;
9152
+ }
9153
+ };
9154
+
9155
+ event.addCommandKeyListener(text, host.onCommandKey.bind(host));
9156
+
9157
+ event.addListener(text, "select", onSelect);
9158
+
9159
+ event.addListener(text, "input", onInput);
9160
+
9161
+ event.addListener(text, "cut", onCut);
9162
+ event.addListener(text, "copy", onCopy);
9163
+ event.addListener(text, "paste", onPaste);
9164
+ if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){
9165
+ event.addListener(parentNode, "keydown", function(e) {
9166
+ if ((useragent.isMac && !e.metaKey) || !e.ctrlKey)
9167
+ return;
9168
+
9169
+ switch (e.keyCode) {
9170
+ case 67:
9171
+ onCopy(e);
9172
+ break;
9173
+ case 86:
9174
+ onPaste(e);
9175
+ break;
9176
+ case 88:
9177
+ onCut(e);
9178
+ break;
9179
+ }
9180
+ });
9181
+ }
9182
+ var onCompositionStart = function(e) {
9183
+ if (inComposition || !host.onCompositionStart || host.$readOnly)
9184
+ return;
9185
+ inComposition = {};
9186
+ host.onCompositionStart();
9187
+ setTimeout(onCompositionUpdate, 0);
9188
+ host.on("mousedown", onCompositionEnd);
9189
+ if (!host.selection.isEmpty()) {
9190
+ host.insert("");
9191
+ host.session.markUndoGroup();
9192
+ host.selection.clearSelection();
9193
+ }
9194
+ host.session.markUndoGroup();
9195
+ };
9196
+
9197
+ var onCompositionUpdate = function() {
9198
+ if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
9199
+ return;
9200
+ var val = text.value.replace(/\x01/g, "");
9201
+ if (inComposition.lastValue === val) return;
9202
+
9203
+ host.onCompositionUpdate(val);
9204
+ if (inComposition.lastValue)
9205
+ host.undo();
9206
+ inComposition.lastValue = val;
9207
+ if (inComposition.lastValue) {
9208
+ var r = host.selection.getRange();
9209
+ host.insert(inComposition.lastValue);
9210
+ host.session.markUndoGroup();
9211
+ inComposition.range = host.selection.getRange();
9212
+ host.selection.setRange(r);
9213
+ host.selection.clearSelection();
9214
+ }
9215
+ };
9216
+
9217
+ var onCompositionEnd = function(e) {
9218
+ if (!host.onCompositionEnd || host.$readOnly) return;
9219
+ var c = inComposition;
9220
+ inComposition = false;
9221
+ var timer = setTimeout(function() {
9222
+ timer = null;
9223
+ var str = text.value.replace(/\x01/g, "");
9224
+ if (inComposition)
9225
+ return;
9226
+ else if (str == c.lastValue)
9227
+ resetValue();
9228
+ else if (!c.lastValue && str) {
9229
+ resetValue();
9230
+ sendText(str);
9231
+ }
9232
+ });
9233
+ inputHandler = function compositionInputHandler(str) {
9234
+ if (timer)
9235
+ clearTimeout(timer);
9236
+ str = str.replace(/\x01/g, "");
9237
+ if (str == c.lastValue)
9238
+ return "";
9239
+ if (c.lastValue && timer)
9240
+ host.undo();
9241
+ return str;
9242
+ };
9243
+ host.onCompositionEnd();
9244
+ host.removeListener("mousedown", onCompositionEnd);
9245
+ if (e.type == "compositionend" && c.range) {
9246
+ host.selection.setRange(c.range);
9247
+ }
9248
+ };
9249
+
9250
+
9251
+
9252
+ var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
9253
+
9254
+ event.addListener(text, "compositionstart", onCompositionStart);
9255
+ if (useragent.isGecko) {
9256
+ event.addListener(text, "text", function(){syncComposition.schedule()});
9257
+ } else {
9258
+ event.addListener(text, "keyup", function(){syncComposition.schedule()});
9259
+ event.addListener(text, "keydown", function(){syncComposition.schedule()});
9260
+ }
9261
+ event.addListener(text, "compositionend", onCompositionEnd);
9262
+
9263
+ this.getElement = function() {
9264
+ return text;
9265
+ };
9266
+
9267
+ this.setReadOnly = function(readOnly) {
9268
+ text.readOnly = readOnly;
9269
+ };
9270
+
9271
+ this.onContextMenu = function(e) {
9272
+ afterContextMenu = true;
9273
+ resetSelection(host.selection.isEmpty());
9274
+ host._emit("nativecontextmenu", {target: host, domEvent: e});
9275
+ this.moveToMouse(e, true);
9276
+ };
9277
+
9278
+ this.moveToMouse = function(e, bringToFront) {
9279
+ if (!bringToFront && useragent.isOldIE)
9280
+ return;
9281
+ if (!tempStyle)
9282
+ tempStyle = text.style.cssText;
9283
+ text.style.cssText = (bringToFront ? "z-index:100000;" : "")
9284
+ + "height:" + text.style.height + ";"
9285
+ + (useragent.isIE ? "opacity:0.1;" : "");
9286
+
9287
+ var rect = host.container.getBoundingClientRect();
9288
+ var style = dom.computedStyle(host.container);
9289
+ var top = rect.top + (parseInt(style.borderTopWidth) || 0);
9290
+ var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
9291
+ var maxTop = rect.bottom - top - text.clientHeight -2;
9292
+ var move = function(e) {
9293
+ text.style.left = e.clientX - left - 2 + "px";
9294
+ text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px";
9295
+ };
9296
+ move(e);
9297
+
9298
+ if (e.type != "mousedown")
9299
+ return;
9300
+
9301
+ if (host.renderer.$keepTextAreaAtCursor)
9302
+ host.renderer.$keepTextAreaAtCursor = null;
9303
+ if (useragent.isWin && !useragent.isOldIE)
9304
+ event.capture(host.container, move, onContextMenuClose);
9305
+ };
9306
+
9307
+ this.onContextMenuClose = onContextMenuClose;
9308
+ var closeTimeout;
9309
+ function onContextMenuClose() {
9310
+ clearTimeout(closeTimeout)
9311
+ closeTimeout = setTimeout(function () {
9312
+ if (tempStyle) {
9313
+ text.style.cssText = tempStyle;
9314
+ tempStyle = '';
9315
+ }
9316
+ if (host.renderer.$keepTextAreaAtCursor == null) {
9317
+ host.renderer.$keepTextAreaAtCursor = true;
9318
+ host.renderer.$moveTextAreaToCursor();
9319
+ }
9320
+ }, useragent.isOldIE ? 200 : 0);
9321
+ }
9322
+
9323
+ var onContextMenu = function(e) {
9324
+ host.textInput.onContextMenu(e);
9325
+ onContextMenuClose();
9326
+ };
9327
+ event.addListener(host.renderer.scroller, "contextmenu", onContextMenu);
9328
+ event.addListener(text, "contextmenu", onContextMenu);
9329
+ };
9330
+
9331
+ exports.TextInput = TextInput;
9332
+ });
9333
+
9334
+ ace.define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) {
9335
+ "use strict";
9336
+
9337
+ var dom = acequire("../lib/dom");
9338
+ var event = acequire("../lib/event");
9339
+ var useragent = acequire("../lib/useragent");
9340
+
9341
+ var DRAG_OFFSET = 0; // pixels
9342
+
9343
+ function DefaultHandlers(mouseHandler) {
9344
+ mouseHandler.$clickSelection = null;
9345
+
9346
+ var editor = mouseHandler.editor;
9347
+ editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler));
9348
+ editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler));
9349
+ editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler));
9350
+ editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler));
9351
+ editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler));
9352
+
9353
+ var exports = ["select", "startSelect", "selectEnd", "selectAllEnd", "selectByWordsEnd",
9354
+ "selectByLinesEnd", "dragWait", "dragWaitEnd", "focusWait"];
9355
+
9356
+ exports.forEach(function(x) {
9357
+ mouseHandler[x] = this[x];
9358
+ }, this);
9359
+
9360
+ mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
9361
+ mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange");
9362
+ }
9363
+
9364
+ (function() {
9365
+
9366
+ this.onMouseDown = function(ev) {
9367
+ var inSelection = ev.inSelection();
9368
+ var pos = ev.getDocumentPosition();
9369
+ this.mousedownEvent = ev;
9370
+ var editor = this.editor;
9371
+
9372
+ var button = ev.getButton();
9373
+ if (button !== 0) {
9374
+ var selectionRange = editor.getSelectionRange();
9375
+ var selectionEmpty = selectionRange.isEmpty();
9376
+
9377
+ if (selectionEmpty)
9378
+ editor.selection.moveToPosition(pos);
9379
+ editor.textInput.onContextMenu(ev.domEvent);
9380
+ return; // stopping event here breaks contextmenu on ff mac
9381
+ }
9382
+
9383
+ this.mousedownEvent.time = Date.now();
9384
+ if (inSelection && !editor.isFocused()) {
9385
+ editor.focus();
9386
+ if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) {
9387
+ this.setState("focusWait");
9388
+ this.captureMouse(ev);
9389
+ return;
9390
+ }
9391
+ }
9392
+
9393
+ this.captureMouse(ev);
9394
+ this.startSelect(pos, ev.domEvent._clicks > 1);
9395
+ return ev.preventDefault();
9396
+ };
9397
+
9398
+ this.startSelect = function(pos, waitForClickSelection) {
9399
+ pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y);
9400
+ var editor = this.editor;
9401
+
9402
+ if (this.mousedownEvent.getShiftKey())
9403
+ editor.selection.selectToPosition(pos);
9404
+ else if (!waitForClickSelection)
9405
+ editor.selection.moveToPosition(pos);
9406
+ if (!waitForClickSelection)
9407
+ this.select();
9408
+ if (editor.renderer.scroller.setCapture) {
9409
+ editor.renderer.scroller.setCapture();
9410
+ }
9411
+ editor.setStyle("ace_selecting");
9412
+ this.setState("select");
9413
+ };
9414
+
9415
+ this.select = function() {
9416
+ var anchor, editor = this.editor;
9417
+ var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
9418
+
9419
+ if (this.$clickSelection) {
9420
+ var cmp = this.$clickSelection.comparePoint(cursor);
9421
+
9422
+ if (cmp == -1) {
9423
+ anchor = this.$clickSelection.end;
9424
+ } else if (cmp == 1) {
9425
+ anchor = this.$clickSelection.start;
9426
+ } else {
9427
+ var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);
9428
+ cursor = orientedRange.cursor;
9429
+ anchor = orientedRange.anchor;
9430
+ }
9431
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
9432
+ }
9433
+ editor.selection.selectToPosition(cursor);
9434
+
9435
+ editor.renderer.scrollCursorIntoView();
9436
+ };
9437
+
9438
+ this.extendSelectionBy = function(unitName) {
9439
+ var anchor, editor = this.editor;
9440
+ var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
9441
+ var range = editor.selection[unitName](cursor.row, cursor.column);
9442
+
9443
+ if (this.$clickSelection) {
9444
+ var cmpStart = this.$clickSelection.comparePoint(range.start);
9445
+ var cmpEnd = this.$clickSelection.comparePoint(range.end);
9446
+
9447
+ if (cmpStart == -1 && cmpEnd <= 0) {
9448
+ anchor = this.$clickSelection.end;
9449
+ if (range.end.row != cursor.row || range.end.column != cursor.column)
9450
+ cursor = range.start;
9451
+ } else if (cmpEnd == 1 && cmpStart >= 0) {
9452
+ anchor = this.$clickSelection.start;
9453
+ if (range.start.row != cursor.row || range.start.column != cursor.column)
9454
+ cursor = range.end;
9455
+ } else if (cmpStart == -1 && cmpEnd == 1) {
9456
+ cursor = range.end;
9457
+ anchor = range.start;
9458
+ } else {
9459
+ var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);
9460
+ cursor = orientedRange.cursor;
9461
+ anchor = orientedRange.anchor;
9462
+ }
9463
+ editor.selection.setSelectionAnchor(anchor.row, anchor.column);
9464
+ }
9465
+ editor.selection.selectToPosition(cursor);
9466
+
9467
+ editor.renderer.scrollCursorIntoView();
9468
+ };
9469
+
9470
+ this.selectEnd =
9471
+ this.selectAllEnd =
9472
+ this.selectByWordsEnd =
9473
+ this.selectByLinesEnd = function() {
9474
+ this.$clickSelection = null;
9475
+ this.editor.unsetStyle("ace_selecting");
9476
+ if (this.editor.renderer.scroller.releaseCapture) {
9477
+ this.editor.renderer.scroller.releaseCapture();
9478
+ }
9479
+ };
9480
+
9481
+ this.focusWait = function() {
9482
+ var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
9483
+ var time = Date.now();
9484
+
9485
+ if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout)
9486
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
9487
+ };
9488
+
9489
+ this.onDoubleClick = function(ev) {
9490
+ var pos = ev.getDocumentPosition();
9491
+ var editor = this.editor;
9492
+ var session = editor.session;
9493
+
9494
+ var range = session.getBracketRange(pos);
9495
+ if (range) {
9496
+ if (range.isEmpty()) {
9497
+ range.start.column--;
9498
+ range.end.column++;
9499
+ }
9500
+ this.setState("select");
9501
+ } else {
9502
+ range = editor.selection.getWordRange(pos.row, pos.column);
9503
+ this.setState("selectByWords");
9504
+ }
9505
+ this.$clickSelection = range;
9506
+ this.select();
9507
+ };
9508
+
9509
+ this.onTripleClick = function(ev) {
9510
+ var pos = ev.getDocumentPosition();
9511
+ var editor = this.editor;
9512
+
9513
+ this.setState("selectByLines");
9514
+ var range = editor.getSelectionRange();
9515
+ if (range.isMultiLine() && range.contains(pos.row, pos.column)) {
9516
+ this.$clickSelection = editor.selection.getLineRange(range.start.row);
9517
+ this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end;
9518
+ } else {
9519
+ this.$clickSelection = editor.selection.getLineRange(pos.row);
9520
+ }
9521
+ this.select();
9522
+ };
9523
+
9524
+ this.onQuadClick = function(ev) {
9525
+ var editor = this.editor;
9526
+
9527
+ editor.selectAll();
9528
+ this.$clickSelection = editor.getSelectionRange();
9529
+ this.setState("selectAll");
9530
+ };
9531
+
9532
+ this.onMouseWheel = function(ev) {
9533
+ if (ev.getAccelKey())
9534
+ return;
9535
+ if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) {
9536
+ ev.wheelX = ev.wheelY;
9537
+ ev.wheelY = 0;
9538
+ }
9539
+
9540
+ var t = ev.domEvent.timeStamp;
9541
+ var dt = t - (this.$lastScrollTime||0);
9542
+
9543
+ var editor = this.editor;
9544
+ var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
9545
+ if (isScrolable || dt < 200) {
9546
+ this.$lastScrollTime = t;
9547
+ editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
9548
+ return ev.stop();
9549
+ }
9550
+ };
9551
+
9552
+ }).call(DefaultHandlers.prototype);
9553
+
9554
+ exports.DefaultHandlers = DefaultHandlers;
9555
+
9556
+ function calcDistance(ax, ay, bx, by) {
9557
+ return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
9558
+ }
9559
+
9560
+ function calcRangeOrientation(range, cursor) {
9561
+ if (range.start.row == range.end.row)
9562
+ var cmp = 2 * cursor.column - range.start.column - range.end.column;
9563
+ else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column)
9564
+ var cmp = cursor.column - 4;
9565
+ else
9566
+ var cmp = 2 * cursor.row - range.start.row - range.end.row;
9567
+
9568
+ if (cmp < 0)
9569
+ return {cursor: range.start, anchor: range.end};
9570
+ else
9571
+ return {cursor: range.end, anchor: range.start};
9572
+ }
9573
+
9574
+ });
9575
+
9576
+ ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(acequire, exports, module) {
9577
+ "use strict";
9578
+
9579
+ var oop = acequire("./lib/oop");
9580
+ var dom = acequire("./lib/dom");
9581
+ function Tooltip (parentNode) {
9582
+ this.isOpen = false;
9583
+ this.$element = null;
9584
+ this.$parentNode = parentNode;
9585
+ }
9586
+
9587
+ (function() {
9588
+ this.$init = function() {
9589
+ this.$element = dom.createElement("div");
9590
+ this.$element.className = "ace_tooltip";
9591
+ this.$element.style.display = "none";
9592
+ this.$parentNode.appendChild(this.$element);
9593
+ return this.$element;
9594
+ };
9595
+ this.getElement = function() {
9596
+ return this.$element || this.$init();
9597
+ };
9598
+ this.setText = function(text) {
9599
+ dom.setInnerText(this.getElement(), text);
9600
+ };
9601
+ this.setHtml = function(html) {
9602
+ this.getElement().innerHTML = html;
9603
+ };
9604
+ this.setPosition = function(x, y) {
9605
+ this.getElement().style.left = x + "px";
9606
+ this.getElement().style.top = y + "px";
9607
+ };
9608
+ this.setClassName = function(className) {
9609
+ dom.addCssClass(this.getElement(), className);
9610
+ };
9611
+ this.show = function(text, x, y) {
9612
+ if (text != null)
9613
+ this.setText(text);
9614
+ if (x != null && y != null)
9615
+ this.setPosition(x, y);
9616
+ if (!this.isOpen) {
9617
+ this.getElement().style.display = "block";
9618
+ this.isOpen = true;
9619
+ }
9620
+ };
9621
+
9622
+ this.hide = function() {
9623
+ if (this.isOpen) {
9624
+ this.getElement().style.display = "none";
9625
+ this.isOpen = false;
9626
+ }
9627
+ };
9628
+ this.getHeight = function() {
9629
+ return this.getElement().offsetHeight;
9630
+ };
9631
+ this.getWidth = function() {
9632
+ return this.getElement().offsetWidth;
9633
+ };
9634
+
9635
+ }).call(Tooltip.prototype);
9636
+
9637
+ exports.Tooltip = Tooltip;
9638
+ });
9639
+
9640
+ ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(acequire, exports, module) {
9641
+ "use strict";
9642
+ var dom = acequire("../lib/dom");
9643
+ var oop = acequire("../lib/oop");
9644
+ var event = acequire("../lib/event");
9645
+ var Tooltip = acequire("../tooltip").Tooltip;
9646
+
9647
+ function GutterHandler(mouseHandler) {
9648
+ var editor = mouseHandler.editor;
9649
+ var gutter = editor.renderer.$gutterLayer;
9650
+ var tooltip = new GutterTooltip(editor.container);
9651
+
9652
+ mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
9653
+ if (!editor.isFocused() || e.getButton() != 0)
9654
+ return;
9655
+ var gutterRegion = gutter.getRegion(e);
9656
+
9657
+ if (gutterRegion == "foldWidgets")
9658
+ return;
9659
+
9660
+ var row = e.getDocumentPosition().row;
9661
+ var selection = editor.session.selection;
9662
+
9663
+ if (e.getShiftKey())
9664
+ selection.selectTo(row, 0);
9665
+ else {
9666
+ if (e.domEvent.detail == 2) {
9667
+ editor.selectAll();
9668
+ return e.preventDefault();
9669
+ }
9670
+ mouseHandler.$clickSelection = editor.selection.getLineRange(row);
9671
+ }
9672
+ mouseHandler.setState("selectByLines");
9673
+ mouseHandler.captureMouse(e);
9674
+ return e.preventDefault();
9675
+ });
9676
+
9677
+
9678
+ var tooltipTimeout, mouseEvent, tooltipAnnotation;
9679
+
9680
+ function showTooltip() {
9681
+ var row = mouseEvent.getDocumentPosition().row;
9682
+ var annotation = gutter.$annotations[row];
9683
+ if (!annotation)
9684
+ return hideTooltip();
9685
+
9686
+ var maxRow = editor.session.getLength();
9687
+ if (row == maxRow) {
9688
+ var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row;
9689
+ var pos = mouseEvent.$pos;
9690
+ if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column))
9691
+ return hideTooltip();
9692
+ }
9693
+
9694
+ if (tooltipAnnotation == annotation)
9695
+ return;
9696
+ tooltipAnnotation = annotation.text.join("<br/>");
9697
+
9698
+ tooltip.setHtml(tooltipAnnotation);
9699
+ tooltip.show();
9700
+ editor.on("mousewheel", hideTooltip);
9701
+
9702
+ if (mouseHandler.$tooltipFollowsMouse) {
9703
+ moveTooltip(mouseEvent);
9704
+ } else {
9705
+ var gutterElement = gutter.$cells[editor.session.documentToScreenRow(row, 0)].element;
9706
+ var rect = gutterElement.getBoundingClientRect();
9707
+ var style = tooltip.getElement().style;
9708
+ style.left = rect.right + "px";
9709
+ style.top = rect.bottom + "px";
9710
+ }
9711
+ }
9712
+
9713
+ function hideTooltip() {
9714
+ if (tooltipTimeout)
9715
+ tooltipTimeout = clearTimeout(tooltipTimeout);
9716
+ if (tooltipAnnotation) {
9717
+ tooltip.hide();
9718
+ tooltipAnnotation = null;
9719
+ editor.removeEventListener("mousewheel", hideTooltip);
9720
+ }
9721
+ }
9722
+
9723
+ function moveTooltip(e) {
9724
+ tooltip.setPosition(e.x, e.y);
9725
+ }
9726
+
9727
+ mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) {
9728
+ var target = e.domEvent.target || e.domEvent.srcElement;
9729
+ if (dom.hasCssClass(target, "ace_fold-widget"))
9730
+ return hideTooltip();
9731
+
9732
+ if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse)
9733
+ moveTooltip(e);
9734
+
9735
+ mouseEvent = e;
9736
+ if (tooltipTimeout)
9737
+ return;
9738
+ tooltipTimeout = setTimeout(function() {
9739
+ tooltipTimeout = null;
9740
+ if (mouseEvent && !mouseHandler.isMousePressed)
9741
+ showTooltip();
9742
+ else
9743
+ hideTooltip();
9744
+ }, 50);
9745
+ });
9746
+
9747
+ event.addListener(editor.renderer.$gutter, "mouseout", function(e) {
9748
+ mouseEvent = null;
9749
+ if (!tooltipAnnotation || tooltipTimeout)
9750
+ return;
9751
+
9752
+ tooltipTimeout = setTimeout(function() {
9753
+ tooltipTimeout = null;
9754
+ hideTooltip();
9755
+ }, 50);
9756
+ });
9757
+
9758
+ editor.on("changeSession", hideTooltip);
9759
+ }
9760
+
9761
+ function GutterTooltip(parentNode) {
9762
+ Tooltip.call(this, parentNode);
9763
+ }
9764
+
9765
+ oop.inherits(GutterTooltip, Tooltip);
9766
+
9767
+ (function(){
9768
+ this.setPosition = function(x, y) {
9769
+ var windowWidth = window.innerWidth || document.documentElement.clientWidth;
9770
+ var windowHeight = window.innerHeight || document.documentElement.clientHeight;
9771
+ var width = this.getWidth();
9772
+ var height = this.getHeight();
9773
+ x += 15;
9774
+ y += 15;
9775
+ if (x + width > windowWidth) {
9776
+ x -= (x + width) - windowWidth;
9777
+ }
9778
+ if (y + height > windowHeight) {
9779
+ y -= 20 + height;
9780
+ }
9781
+ Tooltip.prototype.setPosition.call(this, x, y);
9782
+ };
9783
+
9784
+ }).call(GutterTooltip.prototype);
9785
+
9786
+
9787
+
9788
+ exports.GutterHandler = GutterHandler;
9789
+
9790
+ });
9791
+
9792
+ ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) {
9793
+ "use strict";
9794
+
9795
+ var event = acequire("../lib/event");
9796
+ var useragent = acequire("../lib/useragent");
9797
+ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
9798
+ this.domEvent = domEvent;
9799
+ this.editor = editor;
9800
+
9801
+ this.x = this.clientX = domEvent.clientX;
9802
+ this.y = this.clientY = domEvent.clientY;
9803
+
9804
+ this.$pos = null;
9805
+ this.$inSelection = null;
9806
+
9807
+ this.propagationStopped = false;
9808
+ this.defaultPrevented = false;
9809
+ };
9810
+
9811
+ (function() {
9812
+
9813
+ this.stopPropagation = function() {
9814
+ event.stopPropagation(this.domEvent);
9815
+ this.propagationStopped = true;
9816
+ };
9817
+
9818
+ this.preventDefault = function() {
9819
+ event.preventDefault(this.domEvent);
9820
+ this.defaultPrevented = true;
9821
+ };
9822
+
9823
+ this.stop = function() {
9824
+ this.stopPropagation();
9825
+ this.preventDefault();
9826
+ };
9827
+ this.getDocumentPosition = function() {
9828
+ if (this.$pos)
9829
+ return this.$pos;
9830
+
9831
+ this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY);
9832
+ return this.$pos;
9833
+ };
9834
+ this.inSelection = function() {
9835
+ if (this.$inSelection !== null)
9836
+ return this.$inSelection;
9837
+
9838
+ var editor = this.editor;
9839
+
9840
+
9841
+ var selectionRange = editor.getSelectionRange();
9842
+ if (selectionRange.isEmpty())
9843
+ this.$inSelection = false;
9844
+ else {
9845
+ var pos = this.getDocumentPosition();
9846
+ this.$inSelection = selectionRange.contains(pos.row, pos.column);
9847
+ }
9848
+
9849
+ return this.$inSelection;
9850
+ };
9851
+ this.getButton = function() {
9852
+ return event.getButton(this.domEvent);
9853
+ };
9854
+ this.getShiftKey = function() {
9855
+ return this.domEvent.shiftKey;
9856
+ };
9857
+
9858
+ this.getAccelKey = useragent.isMac
9859
+ ? function() { return this.domEvent.metaKey; }
9860
+ : function() { return this.domEvent.ctrlKey; };
9861
+
9862
+ }).call(MouseEvent.prototype);
9863
+
9864
+ });
9865
+
9866
+ ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) {
9867
+ "use strict";
9868
+
9869
+ var dom = acequire("../lib/dom");
9870
+ var event = acequire("../lib/event");
9871
+ var useragent = acequire("../lib/useragent");
9872
+
9873
+ var AUTOSCROLL_DELAY = 200;
9874
+ var SCROLL_CURSOR_DELAY = 200;
9875
+ var SCROLL_CURSOR_HYSTERESIS = 5;
9876
+
9877
+ function DragdropHandler(mouseHandler) {
9878
+
9879
+ var editor = mouseHandler.editor;
9880
+
9881
+ var blankImage = dom.createElement("img");
9882
+ blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
9883
+ if (useragent.isOpera)
9884
+ blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;";
9885
+
9886
+ var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"];
9887
+
9888
+ exports.forEach(function(x) {
9889
+ mouseHandler[x] = this[x];
9890
+ }, this);
9891
+ editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler));
9892
+
9893
+
9894
+ var mouseTarget = editor.container;
9895
+ var dragSelectionMarker, x, y;
9896
+ var timerId, range;
9897
+ var dragCursor, counter = 0;
9898
+ var dragOperation;
9899
+ var isInternal;
9900
+ var autoScrollStartTime;
9901
+ var cursorMovedTime;
9902
+ var cursorPointOnCaretMoved;
9903
+
9904
+ this.onDragStart = function(e) {
9905
+ if (this.cancelDrag || !mouseTarget.draggable) {
9906
+ var self = this;
9907
+ setTimeout(function(){
9908
+ self.startSelect();
9909
+ self.captureMouse(e);
9910
+ }, 0);
9911
+ return e.preventDefault();
9912
+ }
9913
+ range = editor.getSelectionRange();
9914
+
9915
+ var dataTransfer = e.dataTransfer;
9916
+ dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove";
9917
+ if (useragent.isOpera) {
9918
+ editor.container.appendChild(blankImage);
9919
+ blankImage.scrollTop = 0;
9920
+ }
9921
+ dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0);
9922
+ if (useragent.isOpera) {
9923
+ editor.container.removeChild(blankImage);
9924
+ }
9925
+ dataTransfer.clearData();
9926
+ dataTransfer.setData("Text", editor.session.getTextRange());
9927
+
9928
+ isInternal = true;
9929
+ this.setState("drag");
9930
+ };
9931
+
9932
+ this.onDragEnd = function(e) {
9933
+ mouseTarget.draggable = false;
9934
+ isInternal = false;
9935
+ this.setState(null);
9936
+ if (!editor.getReadOnly()) {
9937
+ var dropEffect = e.dataTransfer.dropEffect;
9938
+ if (!dragOperation && dropEffect == "move")
9939
+ editor.session.remove(editor.getSelectionRange());
9940
+ editor.renderer.$cursorLayer.setBlinking(true);
9941
+ }
9942
+ this.editor.unsetStyle("ace_dragging");
9943
+ this.editor.renderer.setCursorStyle("");
9944
+ };
9945
+
9946
+ this.onDragEnter = function(e) {
9947
+ if (editor.getReadOnly() || !canAccept(e.dataTransfer))
9948
+ return;
9949
+ x = e.clientX;
9950
+ y = e.clientY;
9951
+ if (!dragSelectionMarker)
9952
+ addDragMarker();
9953
+ counter++;
9954
+ e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
9955
+ return event.preventDefault(e);
9956
+ };
9957
+
9958
+ this.onDragOver = function(e) {
9959
+ if (editor.getReadOnly() || !canAccept(e.dataTransfer))
9960
+ return;
9961
+ x = e.clientX;
9962
+ y = e.clientY;
9963
+ if (!dragSelectionMarker) {
9964
+ addDragMarker();
9965
+ counter++;
9966
+ }
9967
+ if (onMouseMoveTimer !== null)
9968
+ onMouseMoveTimer = null;
9969
+
9970
+ e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
9971
+ return event.preventDefault(e);
9972
+ };
9973
+
9974
+ this.onDragLeave = function(e) {
9975
+ counter--;
9976
+ if (counter <= 0 && dragSelectionMarker) {
9977
+ clearDragMarker();
9978
+ dragOperation = null;
9979
+ return event.preventDefault(e);
9980
+ }
9981
+ };
9982
+
9983
+ this.onDrop = function(e) {
9984
+ if (!dragCursor)
9985
+ return;
9986
+ var dataTransfer = e.dataTransfer;
9987
+ if (isInternal) {
9988
+ switch (dragOperation) {
9989
+ case "move":
9990
+ if (range.contains(dragCursor.row, dragCursor.column)) {
9991
+ range = {
9992
+ start: dragCursor,
9993
+ end: dragCursor
9994
+ };
9995
+ } else {
9996
+ range = editor.moveText(range, dragCursor);
9997
+ }
9998
+ break;
9999
+ case "copy":
10000
+ range = editor.moveText(range, dragCursor, true);
10001
+ break;
10002
+ }
10003
+ } else {
10004
+ var dropData = dataTransfer.getData('Text');
10005
+ range = {
10006
+ start: dragCursor,
10007
+ end: editor.session.insert(dragCursor, dropData)
10008
+ };
10009
+ editor.focus();
10010
+ dragOperation = null;
10011
+ }
10012
+ clearDragMarker();
10013
+ return event.preventDefault(e);
10014
+ };
10015
+
10016
+ event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler));
10017
+ event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler));
10018
+ event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler));
10019
+ event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler));
10020
+ event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler));
10021
+ event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler));
10022
+
10023
+ function scrollCursorIntoView(cursor, prevCursor) {
10024
+ var now = Date.now();
10025
+ var vMovement = !prevCursor || cursor.row != prevCursor.row;
10026
+ var hMovement = !prevCursor || cursor.column != prevCursor.column;
10027
+ if (!cursorMovedTime || vMovement || hMovement) {
10028
+ editor.$blockScrolling += 1;
10029
+ editor.moveCursorToPosition(cursor);
10030
+ editor.$blockScrolling -= 1;
10031
+ cursorMovedTime = now;
10032
+ cursorPointOnCaretMoved = {x: x, y: y};
10033
+ } else {
10034
+ var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y);
10035
+ if (distance > SCROLL_CURSOR_HYSTERESIS) {
10036
+ cursorMovedTime = null;
10037
+ } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) {
10038
+ editor.renderer.scrollCursorIntoView();
10039
+ cursorMovedTime = null;
10040
+ }
10041
+ }
10042
+ }
10043
+
10044
+ function autoScroll(cursor, prevCursor) {
10045
+ var now = Date.now();
10046
+ var lineHeight = editor.renderer.layerConfig.lineHeight;
10047
+ var characterWidth = editor.renderer.layerConfig.characterWidth;
10048
+ var editorRect = editor.renderer.scroller.getBoundingClientRect();
10049
+ var offsets = {
10050
+ x: {
10051
+ left: x - editorRect.left,
10052
+ right: editorRect.right - x
10053
+ },
10054
+ y: {
10055
+ top: y - editorRect.top,
10056
+ bottom: editorRect.bottom - y
10057
+ }
10058
+ };
10059
+ var nearestXOffset = Math.min(offsets.x.left, offsets.x.right);
10060
+ var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom);
10061
+ var scrollCursor = {row: cursor.row, column: cursor.column};
10062
+ if (nearestXOffset / characterWidth <= 2) {
10063
+ scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2);
10064
+ }
10065
+ if (nearestYOffset / lineHeight <= 1) {
10066
+ scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1);
10067
+ }
10068
+ var vScroll = cursor.row != scrollCursor.row;
10069
+ var hScroll = cursor.column != scrollCursor.column;
10070
+ var vMovement = !prevCursor || cursor.row != prevCursor.row;
10071
+ if (vScroll || (hScroll && !vMovement)) {
10072
+ if (!autoScrollStartTime)
10073
+ autoScrollStartTime = now;
10074
+ else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY)
10075
+ editor.renderer.scrollCursorIntoView(scrollCursor);
10076
+ } else {
10077
+ autoScrollStartTime = null;
10078
+ }
10079
+ }
10080
+
10081
+ function onDragInterval() {
10082
+ var prevCursor = dragCursor;
10083
+ dragCursor = editor.renderer.screenToTextCoordinates(x, y);
10084
+ scrollCursorIntoView(dragCursor, prevCursor);
10085
+ autoScroll(dragCursor, prevCursor);
10086
+ }
10087
+
10088
+ function addDragMarker() {
10089
+ range = editor.selection.toOrientedRange();
10090
+ dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle());
10091
+ editor.clearSelection();
10092
+ if (editor.isFocused())
10093
+ editor.renderer.$cursorLayer.setBlinking(false);
10094
+ clearInterval(timerId);
10095
+ onDragInterval();
10096
+ timerId = setInterval(onDragInterval, 20);
10097
+ counter = 0;
10098
+ event.addListener(document, "mousemove", onMouseMove);
10099
+ }
10100
+
10101
+ function clearDragMarker() {
10102
+ clearInterval(timerId);
10103
+ editor.session.removeMarker(dragSelectionMarker);
10104
+ dragSelectionMarker = null;
10105
+ editor.$blockScrolling += 1;
10106
+ editor.selection.fromOrientedRange(range);
10107
+ editor.$blockScrolling -= 1;
10108
+ if (editor.isFocused() && !isInternal)
10109
+ editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly());
10110
+ range = null;
10111
+ dragCursor = null;
10112
+ counter = 0;
10113
+ autoScrollStartTime = null;
10114
+ cursorMovedTime = null;
10115
+ event.removeListener(document, "mousemove", onMouseMove);
10116
+ }
10117
+ var onMouseMoveTimer = null;
10118
+ function onMouseMove() {
10119
+ if (onMouseMoveTimer == null) {
10120
+ onMouseMoveTimer = setTimeout(function() {
10121
+ if (onMouseMoveTimer != null && dragSelectionMarker)
10122
+ clearDragMarker();
10123
+ }, 20);
10124
+ }
10125
+ }
10126
+
10127
+ function canAccept(dataTransfer) {
10128
+ var types = dataTransfer.types;
10129
+ return !types || Array.prototype.some.call(types, function(type) {
10130
+ return type == 'text/plain' || type == 'Text';
10131
+ });
10132
+ }
10133
+
10134
+ function getDropEffect(e) {
10135
+ var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized'];
10136
+ var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized'];
10137
+
10138
+ var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey;
10139
+ var effectAllowed = "uninitialized";
10140
+ try {
10141
+ effectAllowed = e.dataTransfer.effectAllowed.toLowerCase();
10142
+ } catch (e) {}
10143
+ var dropEffect = "none";
10144
+
10145
+ if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0)
10146
+ dropEffect = "copy";
10147
+ else if (moveAllowed.indexOf(effectAllowed) >= 0)
10148
+ dropEffect = "move";
10149
+ else if (copyAllowed.indexOf(effectAllowed) >= 0)
10150
+ dropEffect = "copy";
10151
+
10152
+ return dropEffect;
10153
+ }
10154
+ }
10155
+
10156
+ (function() {
10157
+
10158
+ this.dragWait = function() {
10159
+ var interval = Date.now() - this.mousedownEvent.time;
10160
+ if (interval > this.editor.getDragDelay())
10161
+ this.startDrag();
10162
+ };
10163
+
10164
+ this.dragWaitEnd = function() {
10165
+ var target = this.editor.container;
10166
+ target.draggable = false;
10167
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
10168
+ this.selectEnd();
10169
+ };
10170
+
10171
+ this.dragReadyEnd = function(e) {
10172
+ this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly());
10173
+ this.editor.unsetStyle("ace_dragging");
10174
+ this.editor.renderer.setCursorStyle("");
10175
+ this.dragWaitEnd();
10176
+ };
10177
+
10178
+ this.startDrag = function(){
10179
+ this.cancelDrag = false;
10180
+ var editor = this.editor;
10181
+ var target = editor.container;
10182
+ target.draggable = true;
10183
+ editor.renderer.$cursorLayer.setBlinking(false);
10184
+ editor.setStyle("ace_dragging");
10185
+ var cursorStyle = useragent.isWin ? "default" : "move";
10186
+ editor.renderer.setCursorStyle(cursorStyle);
10187
+ this.setState("dragReady");
10188
+ };
10189
+
10190
+ this.onMouseDrag = function(e) {
10191
+ var target = this.editor.container;
10192
+ if (useragent.isIE && this.state == "dragReady") {
10193
+ var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
10194
+ if (distance > 3)
10195
+ target.dragDrop();
10196
+ }
10197
+ if (this.state === "dragWait") {
10198
+ var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
10199
+ if (distance > 0) {
10200
+ target.draggable = false;
10201
+ this.startSelect(this.mousedownEvent.getDocumentPosition());
10202
+ }
10203
+ }
10204
+ };
10205
+
10206
+ this.onMouseDown = function(e) {
10207
+ if (!this.$dragEnabled)
10208
+ return;
10209
+ this.mousedownEvent = e;
10210
+ var editor = this.editor;
10211
+
10212
+ var inSelection = e.inSelection();
10213
+ var button = e.getButton();
10214
+ var clickCount = e.domEvent.detail || 1;
10215
+ if (clickCount === 1 && button === 0 && inSelection) {
10216
+ if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey()))
10217
+ return;
10218
+ this.mousedownEvent.time = Date.now();
10219
+ var eventTarget = e.domEvent.target || e.domEvent.srcElement;
10220
+ if ("unselectable" in eventTarget)
10221
+ eventTarget.unselectable = "on";
10222
+ if (editor.getDragDelay()) {
10223
+ if (useragent.isWebKit) {
10224
+ this.cancelDrag = true;
10225
+ var mouseTarget = editor.container;
10226
+ mouseTarget.draggable = true;
10227
+ }
10228
+ this.setState("dragWait");
10229
+ } else {
10230
+ this.startDrag();
10231
+ }
10232
+ this.captureMouse(e, this.onMouseDrag.bind(this));
10233
+ e.defaultPrevented = true;
10234
+ }
10235
+ };
10236
+
10237
+ }).call(DragdropHandler.prototype);
10238
+
10239
+
10240
+ function calcDistance(ax, ay, bx, by) {
10241
+ return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
10242
+ }
10243
+
10244
+ exports.DragdropHandler = DragdropHandler;
10245
+
10246
+ });
10247
+
10248
+ ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) {
10249
+ "use strict";
10250
+ var dom = acequire("./dom");
10251
+
10252
+ exports.get = function (url, callback) {
10253
+ var xhr = new XMLHttpRequest();
10254
+ xhr.open('GET', url, true);
10255
+ xhr.onreadystatechange = function () {
10256
+ if (xhr.readyState === 4) {
10257
+ callback(xhr.responseText);
10258
+ }
10259
+ };
10260
+ xhr.send(null);
10261
+ };
10262
+
10263
+ exports.loadScript = function(path, callback) {
10264
+ var head = dom.getDocumentHead();
10265
+ var s = document.createElement('script');
10266
+
10267
+ s.src = path;
10268
+ head.appendChild(s);
10269
+
10270
+ s.onload = s.onreadystatechange = function(_, isAbort) {
10271
+ if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") {
10272
+ s = s.onload = s.onreadystatechange = null;
10273
+ if (!isAbort)
10274
+ callback();
10275
+ }
10276
+ };
10277
+ };
10278
+ exports.qualifyURL = function(url) {
10279
+ var a = document.createElement('a');
10280
+ a.href = url;
10281
+ return a.href;
10282
+ }
10283
+
10284
+ });
10285
+
10286
+ ace.define("ace/lib/event_emitter",["require","exports","module"], function(acequire, exports, module) {
10287
+ "use strict";
10288
+
10289
+ var EventEmitter = {};
10290
+ var stopPropagation = function() { this.propagationStopped = true; };
10291
+ var preventDefault = function() { this.defaultPrevented = true; };
10292
+
10293
+ EventEmitter._emit =
10294
+ EventEmitter._dispatchEvent = function(eventName, e) {
10295
+ this._eventRegistry || (this._eventRegistry = {});
10296
+ this._defaultHandlers || (this._defaultHandlers = {});
10297
+
10298
+ var listeners = this._eventRegistry[eventName] || [];
10299
+ var defaultHandler = this._defaultHandlers[eventName];
10300
+ if (!listeners.length && !defaultHandler)
10301
+ return;
10302
+
10303
+ if (typeof e != "object" || !e)
10304
+ e = {};
10305
+
10306
+ if (!e.type)
10307
+ e.type = eventName;
10308
+ if (!e.stopPropagation)
10309
+ e.stopPropagation = stopPropagation;
10310
+ if (!e.preventDefault)
10311
+ e.preventDefault = preventDefault;
10312
+
10313
+ listeners = listeners.slice();
10314
+ for (var i=0; i<listeners.length; i++) {
10315
+ listeners[i](e, this);
10316
+ if (e.propagationStopped)
10317
+ break;
10318
+ }
10319
+
10320
+ if (defaultHandler && !e.defaultPrevented)
10321
+ return defaultHandler(e, this);
10322
+ };
10323
+
10324
+
10325
+ EventEmitter._signal = function(eventName, e) {
10326
+ var listeners = (this._eventRegistry || {})[eventName];
10327
+ if (!listeners)
10328
+ return;
10329
+ listeners = listeners.slice();
10330
+ for (var i=0; i<listeners.length; i++)
10331
+ listeners[i](e, this);
10332
+ };
10333
+
10334
+ EventEmitter.once = function(eventName, callback) {
10335
+ var _self = this;
10336
+ callback && this.addEventListener(eventName, function newCallback() {
10337
+ _self.removeEventListener(eventName, newCallback);
10338
+ callback.apply(null, arguments);
10339
+ });
10340
+ };
10341
+
10342
+
10343
+ EventEmitter.setDefaultHandler = function(eventName, callback) {
10344
+ var handlers = this._defaultHandlers
10345
+ if (!handlers)
10346
+ handlers = this._defaultHandlers = {_disabled_: {}};
10347
+
10348
+ if (handlers[eventName]) {
10349
+ var old = handlers[eventName];
10350
+ var disabled = handlers._disabled_[eventName];
10351
+ if (!disabled)
10352
+ handlers._disabled_[eventName] = disabled = [];
10353
+ disabled.push(old);
10354
+ var i = disabled.indexOf(callback);
10355
+ if (i != -1)
10356
+ disabled.splice(i, 1);
10357
+ }
10358
+ handlers[eventName] = callback;
10359
+ };
10360
+ EventEmitter.removeDefaultHandler = function(eventName, callback) {
10361
+ var handlers = this._defaultHandlers
10362
+ if (!handlers)
10363
+ return;
10364
+ var disabled = handlers._disabled_[eventName];
10365
+
10366
+ if (handlers[eventName] == callback) {
10367
+ var old = handlers[eventName];
10368
+ if (disabled)
10369
+ this.setDefaultHandler(eventName, disabled.pop());
10370
+ } else if (disabled) {
10371
+ var i = disabled.indexOf(callback);
10372
+ if (i != -1)
10373
+ disabled.splice(i, 1);
10374
+ }
10375
+ };
10376
+
10377
+ EventEmitter.on =
10378
+ EventEmitter.addEventListener = function(eventName, callback, capturing) {
10379
+ this._eventRegistry = this._eventRegistry || {};
10380
+
10381
+ var listeners = this._eventRegistry[eventName];
10382
+ if (!listeners)
10383
+ listeners = this._eventRegistry[eventName] = [];
10384
+
10385
+ if (listeners.indexOf(callback) == -1)
10386
+ listeners[capturing ? "unshift" : "push"](callback);
10387
+ return callback;
10388
+ };
10389
+
10390
+ EventEmitter.off =
10391
+ EventEmitter.removeListener =
10392
+ EventEmitter.removeEventListener = function(eventName, callback) {
10393
+ this._eventRegistry = this._eventRegistry || {};
10394
+
10395
+ var listeners = this._eventRegistry[eventName];
10396
+ if (!listeners)
10397
+ return;
10398
+
10399
+ var index = listeners.indexOf(callback);
10400
+ if (index !== -1)
10401
+ listeners.splice(index, 1);
10402
+ };
10403
+
10404
+ EventEmitter.removeAllListeners = function(eventName) {
10405
+ if (this._eventRegistry) this._eventRegistry[eventName] = [];
10406
+ };
10407
+
10408
+ exports.EventEmitter = EventEmitter;
10409
+
10410
+ });
10411
+
10412
+ ace.define("ace/config",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/lib/net","ace/lib/event_emitter"], function(acequire, exports, module) {
10413
+ "no use strict";
10414
+
10415
+ var lang = acequire("./lib/lang");
10416
+ var oop = acequire("./lib/oop");
10417
+ var net = acequire("./lib/net");
10418
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
10419
+
10420
+ var global = (function() {
10421
+ return this;
10422
+ })();
10423
+
10424
+ var options = {
10425
+ packaged: false,
10426
+ workerPath: null,
10427
+ modePath: null,
10428
+ themePath: null,
10429
+ basePath: "",
10430
+ suffix: ".js",
10431
+ $moduleUrls: {}
10432
+ };
10433
+
10434
+ exports.get = function(key) {
10435
+ if (!options.hasOwnProperty(key))
10436
+ throw new Error("Unknown config key: " + key);
10437
+
10438
+ return options[key];
10439
+ };
10440
+
10441
+ exports.set = function(key, value) {
10442
+ if (!options.hasOwnProperty(key))
10443
+ throw new Error("Unknown config key: " + key);
10444
+
10445
+ options[key] = value;
10446
+ };
10447
+
10448
+ exports.all = function() {
10449
+ return lang.copyObject(options);
10450
+ };
10451
+ oop.implement(exports, EventEmitter);
10452
+
10453
+ exports.moduleUrl = function(name, component) {
10454
+ if (options.$moduleUrls[name])
10455
+ return options.$moduleUrls[name];
10456
+
10457
+ var parts = name.split("/");
10458
+ component = component || parts[parts.length - 2] || "";
10459
+ var sep = component == "snippets" ? "/" : "-";
10460
+ var base = parts[parts.length - 1];
10461
+ if (component == "worker" && sep == "-") {
10462
+ var re = new RegExp("^" + component + "[\\-_]|[\\-_]" + component + "$", "g");
10463
+ base = base.replace(re, "");
10464
+ }
10465
+
10466
+ if ((!base || base == component) && parts.length > 1)
10467
+ base = parts[parts.length - 2];
10468
+ var path = options[component + "Path"];
10469
+ if (path == null) {
10470
+ path = options.basePath;
10471
+ } else if (sep == "/") {
10472
+ component = sep = "";
10473
+ }
10474
+ if (path && path.slice(-1) != "/")
10475
+ path += "/";
10476
+ return path + component + sep + base + this.get("suffix");
10477
+ };
10478
+
10479
+ exports.setModuleUrl = function(name, subst) {
10480
+ return options.$moduleUrls[name] = subst;
10481
+ };
10482
+
10483
+ exports.$loading = {};
10484
+ exports.loadModule = function(moduleName, onLoad) {
10485
+ var module, moduleType;
10486
+ if (Array.isArray(moduleName)) {
10487
+ moduleType = moduleName[0];
10488
+ moduleName = moduleName[1];
10489
+ }
10490
+
10491
+ try {
10492
+ module = acequire(moduleName);
10493
+ } catch (e) {}
10494
+ if (module && !exports.$loading[moduleName])
10495
+ return onLoad && onLoad(module);
10496
+
10497
+ if (!exports.$loading[moduleName])
10498
+ exports.$loading[moduleName] = [];
10499
+
10500
+ exports.$loading[moduleName].push(onLoad);
10501
+
10502
+ if (exports.$loading[moduleName].length > 1)
10503
+ return;
10504
+
10505
+ var afterLoad = function() {
10506
+ acequire([moduleName], function(module) {
10507
+ exports._emit("load.module", {name: moduleName, module: module});
10508
+ var listeners = exports.$loading[moduleName];
10509
+ exports.$loading[moduleName] = null;
10510
+ listeners.forEach(function(onLoad) {
10511
+ onLoad && onLoad(module);
10512
+ });
10513
+ });
10514
+ };
10515
+
10516
+ if (!exports.get("packaged"))
10517
+ return afterLoad();
10518
+ net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
10519
+ };
10520
+ init(true);function init(packaged) {
10521
+
10522
+ options.packaged = packaged || acequire.packaged || module.packaged || (global.define && __webpack_require__(18).packaged);
10523
+
10524
+ if (!global.document)
10525
+ return "";
10526
+
10527
+ var scriptOptions = {};
10528
+ var scriptUrl = "";
10529
+ var currentScript = (document.currentScript || document._currentScript ); // native or polyfill
10530
+ var currentDocument = currentScript && currentScript.ownerDocument || document;
10531
+
10532
+ var scripts = currentDocument.getElementsByTagName("script");
10533
+ for (var i=0; i<scripts.length; i++) {
10534
+ var script = scripts[i];
10535
+
10536
+ var src = script.src || script.getAttribute("src");
10537
+ if (!src)
10538
+ continue;
10539
+
10540
+ var attributes = script.attributes;
10541
+ for (var j=0, l=attributes.length; j < l; j++) {
10542
+ var attr = attributes[j];
10543
+ if (attr.name.indexOf("data-ace-") === 0) {
10544
+ scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
10545
+ }
10546
+ }
10547
+
10548
+ var m = src.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);
10549
+ if (m)
10550
+ scriptUrl = m[1];
10551
+ }
10552
+
10553
+ if (scriptUrl) {
10554
+ scriptOptions.base = scriptOptions.base || scriptUrl;
10555
+ scriptOptions.packaged = true;
10556
+ }
10557
+
10558
+ scriptOptions.basePath = scriptOptions.base;
10559
+ scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
10560
+ scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
10561
+ scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
10562
+ delete scriptOptions.base;
10563
+
10564
+ for (var key in scriptOptions)
10565
+ if (typeof scriptOptions[key] !== "undefined")
10566
+ exports.set(key, scriptOptions[key]);
10567
+ };
10568
+
10569
+ exports.init = init;
10570
+
10571
+ function deHyphenate(str) {
10572
+ return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
10573
+ }
10574
+
10575
+ var optionsProvider = {
10576
+ setOptions: function(optList) {
10577
+ Object.keys(optList).forEach(function(key) {
10578
+ this.setOption(key, optList[key]);
10579
+ }, this);
10580
+ },
10581
+ getOptions: function(optionNames) {
10582
+ var result = {};
10583
+ if (!optionNames) {
10584
+ optionNames = Object.keys(this.$options);
10585
+ } else if (!Array.isArray(optionNames)) {
10586
+ result = optionNames;
10587
+ optionNames = Object.keys(result);
10588
+ }
10589
+ optionNames.forEach(function(key) {
10590
+ result[key] = this.getOption(key);
10591
+ }, this);
10592
+ return result;
10593
+ },
10594
+ setOption: function(name, value) {
10595
+ if (this["$" + name] === value)
10596
+ return;
10597
+ var opt = this.$options[name];
10598
+ if (!opt) {
10599
+ if (typeof console != "undefined" && console.warn)
10600
+ console.warn('misspelled option "' + name + '"');
10601
+ return undefined;
10602
+ }
10603
+ if (opt.forwardTo)
10604
+ return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value);
10605
+
10606
+ if (!opt.handlesSet)
10607
+ this["$" + name] = value;
10608
+ if (opt && opt.set)
10609
+ opt.set.call(this, value);
10610
+ },
10611
+ getOption: function(name) {
10612
+ var opt = this.$options[name];
10613
+ if (!opt) {
10614
+ if (typeof console != "undefined" && console.warn)
10615
+ console.warn('misspelled option "' + name + '"');
10616
+ return undefined;
10617
+ }
10618
+ if (opt.forwardTo)
10619
+ return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
10620
+ return opt && opt.get ? opt.get.call(this) : this["$" + name];
10621
+ }
10622
+ };
10623
+
10624
+ var defaultOptions = {};
10625
+ exports.defineOptions = function(obj, path, options) {
10626
+ if (!obj.$options)
10627
+ defaultOptions[path] = obj.$options = {};
10628
+
10629
+ Object.keys(options).forEach(function(key) {
10630
+ var opt = options[key];
10631
+ if (typeof opt == "string")
10632
+ opt = {forwardTo: opt};
10633
+
10634
+ opt.name || (opt.name = key);
10635
+ obj.$options[opt.name] = opt;
10636
+ if ("initialValue" in opt)
10637
+ obj["$" + opt.name] = opt.initialValue;
10638
+ });
10639
+ oop.implement(obj, optionsProvider);
10640
+
10641
+ return this;
10642
+ };
10643
+
10644
+ exports.resetOptions = function(obj) {
10645
+ Object.keys(obj.$options).forEach(function(key) {
10646
+ var opt = obj.$options[key];
10647
+ if ("value" in opt)
10648
+ obj.setOption(key, opt.value);
10649
+ });
10650
+ };
10651
+
10652
+ exports.setDefaultValue = function(path, name, value) {
10653
+ var opts = defaultOptions[path] || (defaultOptions[path] = {});
10654
+ if (opts[name]) {
10655
+ if (opts.forwardTo)
10656
+ exports.setDefaultValue(opts.forwardTo, name, value);
10657
+ else
10658
+ opts[name].value = value;
10659
+ }
10660
+ };
10661
+
10662
+ exports.setDefaultValues = function(path, optionHash) {
10663
+ Object.keys(optionHash).forEach(function(key) {
10664
+ exports.setDefaultValue(path, key, optionHash[key]);
10665
+ });
10666
+ };
10667
+
10668
+ });
10669
+
10670
+ ace.define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"], function(acequire, exports, module) {
10671
+ "use strict";
10672
+
10673
+ var event = acequire("../lib/event");
10674
+ var useragent = acequire("../lib/useragent");
10675
+ var DefaultHandlers = acequire("./default_handlers").DefaultHandlers;
10676
+ var DefaultGutterHandler = acequire("./default_gutter_handler").GutterHandler;
10677
+ var MouseEvent = acequire("./mouse_event").MouseEvent;
10678
+ var DragdropHandler = acequire("./dragdrop_handler").DragdropHandler;
10679
+ var config = acequire("../config");
10680
+
10681
+ var MouseHandler = function(editor) {
10682
+ var _self = this;
10683
+ this.editor = editor;
10684
+
10685
+ new DefaultHandlers(this);
10686
+ new DefaultGutterHandler(this);
10687
+ new DragdropHandler(this);
10688
+
10689
+ var focusEditor = function(e) {
10690
+ if (!editor.isFocused() && editor.textInput)
10691
+ editor.textInput.moveToMouse(e);
10692
+ editor.focus()
10693
+ };
10694
+
10695
+ var mouseTarget = editor.renderer.getMouseEventTarget();
10696
+ event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click"));
10697
+ event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove"));
10698
+ event.addMultiMouseDownListener(mouseTarget, [400, 300, 250], this, "onMouseEvent");
10699
+ if (editor.renderer.scrollBarV) {
10700
+ event.addMultiMouseDownListener(editor.renderer.scrollBarV.inner, [400, 300, 250], this, "onMouseEvent");
10701
+ event.addMultiMouseDownListener(editor.renderer.scrollBarH.inner, [400, 300, 250], this, "onMouseEvent");
10702
+ if (useragent.isIE) {
10703
+ event.addListener(editor.renderer.scrollBarV.element, "mousedown", focusEditor);
10704
+ event.addListener(editor.renderer.scrollBarH.element, "mousemove", focusEditor);
10705
+ }
10706
+ }
10707
+ event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel"));
10708
+
10709
+ var gutterEl = editor.renderer.$gutter;
10710
+ event.addListener(gutterEl, "mousedown", this.onMouseEvent.bind(this, "guttermousedown"));
10711
+ event.addListener(gutterEl, "click", this.onMouseEvent.bind(this, "gutterclick"));
10712
+ event.addListener(gutterEl, "dblclick", this.onMouseEvent.bind(this, "gutterdblclick"));
10713
+ event.addListener(gutterEl, "mousemove", this.onMouseEvent.bind(this, "guttermousemove"));
10714
+
10715
+ event.addListener(mouseTarget, "mousedown", focusEditor);
10716
+
10717
+ event.addListener(gutterEl, "mousedown", function(e) {
10718
+ editor.focus();
10719
+ return event.preventDefault(e);
10720
+ });
10721
+
10722
+ editor.on("mousemove", function(e){
10723
+ if (_self.state || _self.$dragDelay || !_self.$dragEnabled)
10724
+ return;
10725
+
10726
+ var char = editor.renderer.screenToTextCoordinates(e.x, e.y);
10727
+ var range = editor.session.selection.getRange();
10728
+ var renderer = editor.renderer;
10729
+
10730
+ if (!range.isEmpty() && range.insideStart(char.row, char.column)) {
10731
+ renderer.setCursorStyle("default");
10732
+ } else {
10733
+ renderer.setCursorStyle("");
10734
+ }
10735
+ });
10736
+ };
10737
+
10738
+ (function() {
10739
+ this.onMouseEvent = function(name, e) {
10740
+ this.editor._emit(name, new MouseEvent(e, this.editor));
10741
+ };
10742
+
10743
+ this.onMouseMove = function(name, e) {
10744
+ var listeners = this.editor._eventRegistry && this.editor._eventRegistry.mousemove;
10745
+ if (!listeners || !listeners.length)
10746
+ return;
10747
+
10748
+ this.editor._emit(name, new MouseEvent(e, this.editor));
10749
+ };
10750
+
10751
+ this.onMouseWheel = function(name, e) {
10752
+ var mouseEvent = new MouseEvent(e, this.editor);
10753
+ mouseEvent.speed = this.$scrollSpeed * 2;
10754
+ mouseEvent.wheelX = e.wheelX;
10755
+ mouseEvent.wheelY = e.wheelY;
10756
+
10757
+ this.editor._emit(name, mouseEvent);
10758
+ };
10759
+
10760
+ this.setState = function(state) {
10761
+ this.state = state;
10762
+ };
10763
+
10764
+ this.captureMouse = function(ev, mouseMoveHandler) {
10765
+ this.x = ev.x;
10766
+ this.y = ev.y;
10767
+
10768
+ this.isMousePressed = true;
10769
+ var renderer = this.editor.renderer;
10770
+ if (renderer.$keepTextAreaAtCursor)
10771
+ renderer.$keepTextAreaAtCursor = null;
10772
+
10773
+ var self = this;
10774
+ var onMouseMove = function(e) {
10775
+ if (!e) return;
10776
+ if (useragent.isWebKit && !e.which && self.releaseMouse)
10777
+ return self.releaseMouse();
10778
+
10779
+ self.x = e.clientX;
10780
+ self.y = e.clientY;
10781
+ mouseMoveHandler && mouseMoveHandler(e);
10782
+ self.mouseEvent = new MouseEvent(e, self.editor);
10783
+ self.$mouseMoved = true;
10784
+ };
10785
+
10786
+ var onCaptureEnd = function(e) {
10787
+ clearInterval(timerId);
10788
+ onCaptureInterval();
10789
+ self[self.state + "End"] && self[self.state + "End"](e);
10790
+ self.state = "";
10791
+ if (renderer.$keepTextAreaAtCursor == null) {
10792
+ renderer.$keepTextAreaAtCursor = true;
10793
+ renderer.$moveTextAreaToCursor();
10794
+ }
10795
+ self.isMousePressed = false;
10796
+ self.$onCaptureMouseMove = self.releaseMouse = null;
10797
+ e && self.onMouseEvent("mouseup", e);
10798
+ };
10799
+
10800
+ var onCaptureInterval = function() {
10801
+ self[self.state] && self[self.state]();
10802
+ self.$mouseMoved = false;
10803
+ };
10804
+
10805
+ if (useragent.isOldIE && ev.domEvent.type == "dblclick") {
10806
+ return setTimeout(function() {onCaptureEnd(ev);});
10807
+ }
10808
+
10809
+ self.$onCaptureMouseMove = onMouseMove;
10810
+ self.releaseMouse = event.capture(this.editor.container, onMouseMove, onCaptureEnd);
10811
+ var timerId = setInterval(onCaptureInterval, 20);
10812
+ };
10813
+ this.releaseMouse = null;
10814
+ this.cancelContextMenu = function() {
10815
+ var stop = function(e) {
10816
+ if (e && e.domEvent && e.domEvent.type != "contextmenu")
10817
+ return;
10818
+ this.editor.off("nativecontextmenu", stop);
10819
+ if (e && e.domEvent)
10820
+ event.stopEvent(e.domEvent);
10821
+ }.bind(this);
10822
+ setTimeout(stop, 10);
10823
+ this.editor.on("nativecontextmenu", stop);
10824
+ };
10825
+ }).call(MouseHandler.prototype);
10826
+
10827
+ config.defineOptions(MouseHandler.prototype, "mouseHandler", {
10828
+ scrollSpeed: {initialValue: 2},
10829
+ dragDelay: {initialValue: (useragent.isMac ? 150 : 0)},
10830
+ dragEnabled: {initialValue: true},
10831
+ focusTimout: {initialValue: 0},
10832
+ tooltipFollowsMouse: {initialValue: true}
10833
+ });
10834
+
10835
+
10836
+ exports.MouseHandler = MouseHandler;
10837
+ });
10838
+
10839
+ ace.define("ace/mouse/fold_handler",["require","exports","module"], function(acequire, exports, module) {
10840
+ "use strict";
10841
+
10842
+ function FoldHandler(editor) {
10843
+
10844
+ editor.on("click", function(e) {
10845
+ var position = e.getDocumentPosition();
10846
+ var session = editor.session;
10847
+ var fold = session.getFoldAt(position.row, position.column, 1);
10848
+ if (fold) {
10849
+ if (e.getAccelKey())
10850
+ session.removeFold(fold);
10851
+ else
10852
+ session.expandFold(fold);
10853
+
10854
+ e.stop();
10855
+ }
10856
+ });
10857
+
10858
+ editor.on("gutterclick", function(e) {
10859
+ var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
10860
+
10861
+ if (gutterRegion == "foldWidgets") {
10862
+ var row = e.getDocumentPosition().row;
10863
+ var session = editor.session;
10864
+ if (session.foldWidgets && session.foldWidgets[row])
10865
+ editor.session.onFoldWidgetClick(row, e);
10866
+ if (!editor.isFocused())
10867
+ editor.focus();
10868
+ e.stop();
10869
+ }
10870
+ });
10871
+
10872
+ editor.on("gutterdblclick", function(e) {
10873
+ var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
10874
+
10875
+ if (gutterRegion == "foldWidgets") {
10876
+ var row = e.getDocumentPosition().row;
10877
+ var session = editor.session;
10878
+ var data = session.getParentFoldRangeData(row, true);
10879
+ var range = data.range || data.firstRange;
10880
+
10881
+ if (range) {
10882
+ row = range.start.row;
10883
+ var fold = session.getFoldAt(row, session.getLine(row).length, 1);
10884
+
10885
+ if (fold) {
10886
+ session.removeFold(fold);
10887
+ } else {
10888
+ session.addFold("...", range);
10889
+ editor.renderer.scrollCursorIntoView({row: range.start.row, column: 0});
10890
+ }
10891
+ }
10892
+ e.stop();
10893
+ }
10894
+ });
10895
+ }
10896
+
10897
+ exports.FoldHandler = FoldHandler;
10898
+
10899
+ });
10900
+
10901
+ ace.define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"], function(acequire, exports, module) {
10902
+ "use strict";
10903
+
10904
+ var keyUtil = acequire("../lib/keys");
10905
+ var event = acequire("../lib/event");
10906
+
10907
+ var KeyBinding = function(editor) {
10908
+ this.$editor = editor;
10909
+ this.$data = {editor: editor};
10910
+ this.$handlers = [];
10911
+ this.setDefaultHandler(editor.commands);
10912
+ };
10913
+
10914
+ (function() {
10915
+ this.setDefaultHandler = function(kb) {
10916
+ this.removeKeyboardHandler(this.$defaultHandler);
10917
+ this.$defaultHandler = kb;
10918
+ this.addKeyboardHandler(kb, 0);
10919
+ };
10920
+
10921
+ this.setKeyboardHandler = function(kb) {
10922
+ var h = this.$handlers;
10923
+ if (h[h.length - 1] == kb)
10924
+ return;
10925
+
10926
+ while (h[h.length - 1] && h[h.length - 1] != this.$defaultHandler)
10927
+ this.removeKeyboardHandler(h[h.length - 1]);
10928
+
10929
+ this.addKeyboardHandler(kb, 1);
10930
+ };
10931
+
10932
+ this.addKeyboardHandler = function(kb, pos) {
10933
+ if (!kb)
10934
+ return;
10935
+ if (typeof kb == "function" && !kb.handleKeyboard)
10936
+ kb.handleKeyboard = kb;
10937
+ var i = this.$handlers.indexOf(kb);
10938
+ if (i != -1)
10939
+ this.$handlers.splice(i, 1);
10940
+
10941
+ if (pos == undefined)
10942
+ this.$handlers.push(kb);
10943
+ else
10944
+ this.$handlers.splice(pos, 0, kb);
10945
+
10946
+ if (i == -1 && kb.attach)
10947
+ kb.attach(this.$editor);
10948
+ };
10949
+
10950
+ this.removeKeyboardHandler = function(kb) {
10951
+ var i = this.$handlers.indexOf(kb);
10952
+ if (i == -1)
10953
+ return false;
10954
+ this.$handlers.splice(i, 1);
10955
+ kb.detach && kb.detach(this.$editor);
10956
+ return true;
10957
+ };
10958
+
10959
+ this.getKeyboardHandler = function() {
10960
+ return this.$handlers[this.$handlers.length - 1];
10961
+ };
10962
+
10963
+ this.getStatusText = function() {
10964
+ var data = this.$data;
10965
+ var editor = data.editor;
10966
+ return this.$handlers.map(function(h) {
10967
+ return h.getStatusText && h.getStatusText(editor, data) || "";
10968
+ }).filter(Boolean).join(" ");
10969
+ };
10970
+
10971
+ this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) {
10972
+ var toExecute;
10973
+ var success = false;
10974
+ var commands = this.$editor.commands;
10975
+
10976
+ for (var i = this.$handlers.length; i--;) {
10977
+ toExecute = this.$handlers[i].handleKeyboard(
10978
+ this.$data, hashId, keyString, keyCode, e
10979
+ );
10980
+ if (!toExecute || !toExecute.command)
10981
+ continue;
10982
+ if (toExecute.command == "null") {
10983
+ success = true;
10984
+ } else {
10985
+ success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
10986
+ }
10987
+ if (success && e && hashId != -1 &&
10988
+ toExecute.passEvent != true && toExecute.command.passEvent != true
10989
+ ) {
10990
+ event.stopEvent(e);
10991
+ }
10992
+ if (success)
10993
+ break;
10994
+ }
10995
+ return success;
10996
+ };
10997
+
10998
+ this.onCommandKey = function(e, hashId, keyCode) {
10999
+ var keyString = keyUtil.keyCodeToString(keyCode);
11000
+ this.$callKeyboardHandlers(hashId, keyString, keyCode, e);
11001
+ };
11002
+
11003
+ this.onTextInput = function(text) {
11004
+ var success = this.$callKeyboardHandlers(-1, text);
11005
+ if (!success)
11006
+ this.$editor.commands.exec("insertstring", this.$editor, text);
11007
+ };
11008
+
11009
+ }).call(KeyBinding.prototype);
11010
+
11011
+ exports.KeyBinding = KeyBinding;
11012
+ });
11013
+
11014
+ ace.define("ace/range",["require","exports","module"], function(acequire, exports, module) {
11015
+ "use strict";
11016
+ var comparePoints = function(p1, p2) {
11017
+ return p1.row - p2.row || p1.column - p2.column;
11018
+ };
11019
+ var Range = function(startRow, startColumn, endRow, endColumn) {
11020
+ this.start = {
11021
+ row: startRow,
11022
+ column: startColumn
11023
+ };
11024
+
11025
+ this.end = {
11026
+ row: endRow,
11027
+ column: endColumn
11028
+ };
11029
+ };
11030
+
11031
+ (function() {
11032
+ this.isEqual = function(range) {
11033
+ return this.start.row === range.start.row &&
11034
+ this.end.row === range.end.row &&
11035
+ this.start.column === range.start.column &&
11036
+ this.end.column === range.end.column;
11037
+ };
11038
+ this.toString = function() {
11039
+ return ("Range: [" + this.start.row + "/" + this.start.column +
11040
+ "] -> [" + this.end.row + "/" + this.end.column + "]");
11041
+ };
11042
+
11043
+ this.contains = function(row, column) {
11044
+ return this.compare(row, column) == 0;
11045
+ };
11046
+ this.compareRange = function(range) {
11047
+ var cmp,
11048
+ end = range.end,
11049
+ start = range.start;
11050
+
11051
+ cmp = this.compare(end.row, end.column);
11052
+ if (cmp == 1) {
11053
+ cmp = this.compare(start.row, start.column);
11054
+ if (cmp == 1) {
11055
+ return 2;
11056
+ } else if (cmp == 0) {
11057
+ return 1;
11058
+ } else {
11059
+ return 0;
11060
+ }
11061
+ } else if (cmp == -1) {
11062
+ return -2;
11063
+ } else {
11064
+ cmp = this.compare(start.row, start.column);
11065
+ if (cmp == -1) {
11066
+ return -1;
11067
+ } else if (cmp == 1) {
11068
+ return 42;
11069
+ } else {
11070
+ return 0;
11071
+ }
11072
+ }
11073
+ };
11074
+ this.comparePoint = function(p) {
11075
+ return this.compare(p.row, p.column);
11076
+ };
11077
+ this.containsRange = function(range) {
11078
+ return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
11079
+ };
11080
+ this.intersects = function(range) {
11081
+ var cmp = this.compareRange(range);
11082
+ return (cmp == -1 || cmp == 0 || cmp == 1);
11083
+ };
11084
+ this.isEnd = function(row, column) {
11085
+ return this.end.row == row && this.end.column == column;
11086
+ };
11087
+ this.isStart = function(row, column) {
11088
+ return this.start.row == row && this.start.column == column;
11089
+ };
11090
+ this.setStart = function(row, column) {
11091
+ if (typeof row == "object") {
11092
+ this.start.column = row.column;
11093
+ this.start.row = row.row;
11094
+ } else {
11095
+ this.start.row = row;
11096
+ this.start.column = column;
11097
+ }
11098
+ };
11099
+ this.setEnd = function(row, column) {
11100
+ if (typeof row == "object") {
11101
+ this.end.column = row.column;
11102
+ this.end.row = row.row;
11103
+ } else {
11104
+ this.end.row = row;
11105
+ this.end.column = column;
11106
+ }
11107
+ };
11108
+ this.inside = function(row, column) {
11109
+ if (this.compare(row, column) == 0) {
11110
+ if (this.isEnd(row, column) || this.isStart(row, column)) {
11111
+ return false;
11112
+ } else {
11113
+ return true;
11114
+ }
11115
+ }
11116
+ return false;
11117
+ };
11118
+ this.insideStart = function(row, column) {
11119
+ if (this.compare(row, column) == 0) {
11120
+ if (this.isEnd(row, column)) {
11121
+ return false;
11122
+ } else {
11123
+ return true;
11124
+ }
11125
+ }
11126
+ return false;
11127
+ };
11128
+ this.insideEnd = function(row, column) {
11129
+ if (this.compare(row, column) == 0) {
11130
+ if (this.isStart(row, column)) {
11131
+ return false;
11132
+ } else {
11133
+ return true;
11134
+ }
11135
+ }
11136
+ return false;
11137
+ };
11138
+ this.compare = function(row, column) {
11139
+ if (!this.isMultiLine()) {
11140
+ if (row === this.start.row) {
11141
+ return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
11142
+ };
11143
+ }
11144
+
11145
+ if (row < this.start.row)
11146
+ return -1;
11147
+
11148
+ if (row > this.end.row)
11149
+ return 1;
11150
+
11151
+ if (this.start.row === row)
11152
+ return column >= this.start.column ? 0 : -1;
11153
+
11154
+ if (this.end.row === row)
11155
+ return column <= this.end.column ? 0 : 1;
11156
+
11157
+ return 0;
11158
+ };
11159
+ this.compareStart = function(row, column) {
11160
+ if (this.start.row == row && this.start.column == column) {
11161
+ return -1;
11162
+ } else {
11163
+ return this.compare(row, column);
11164
+ }
11165
+ };
11166
+ this.compareEnd = function(row, column) {
11167
+ if (this.end.row == row && this.end.column == column) {
11168
+ return 1;
11169
+ } else {
11170
+ return this.compare(row, column);
11171
+ }
11172
+ };
11173
+ this.compareInside = function(row, column) {
11174
+ if (this.end.row == row && this.end.column == column) {
11175
+ return 1;
11176
+ } else if (this.start.row == row && this.start.column == column) {
11177
+ return -1;
11178
+ } else {
11179
+ return this.compare(row, column);
11180
+ }
11181
+ };
11182
+ this.clipRows = function(firstRow, lastRow) {
11183
+ if (this.end.row > lastRow)
11184
+ var end = {row: lastRow + 1, column: 0};
11185
+ else if (this.end.row < firstRow)
11186
+ var end = {row: firstRow, column: 0};
11187
+
11188
+ if (this.start.row > lastRow)
11189
+ var start = {row: lastRow + 1, column: 0};
11190
+ else if (this.start.row < firstRow)
11191
+ var start = {row: firstRow, column: 0};
11192
+
11193
+ return Range.fromPoints(start || this.start, end || this.end);
11194
+ };
11195
+ this.extend = function(row, column) {
11196
+ var cmp = this.compare(row, column);
11197
+
11198
+ if (cmp == 0)
11199
+ return this;
11200
+ else if (cmp == -1)
11201
+ var start = {row: row, column: column};
11202
+ else
11203
+ var end = {row: row, column: column};
11204
+
11205
+ return Range.fromPoints(start || this.start, end || this.end);
11206
+ };
11207
+
11208
+ this.isEmpty = function() {
11209
+ return (this.start.row === this.end.row && this.start.column === this.end.column);
11210
+ };
11211
+ this.isMultiLine = function() {
11212
+ return (this.start.row !== this.end.row);
11213
+ };
11214
+ this.clone = function() {
11215
+ return Range.fromPoints(this.start, this.end);
11216
+ };
11217
+ this.collapseRows = function() {
11218
+ if (this.end.column == 0)
11219
+ return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
11220
+ else
11221
+ return new Range(this.start.row, 0, this.end.row, 0)
11222
+ };
11223
+ this.toScreenRange = function(session) {
11224
+ var screenPosStart = session.documentToScreenPosition(this.start);
11225
+ var screenPosEnd = session.documentToScreenPosition(this.end);
11226
+
11227
+ return new Range(
11228
+ screenPosStart.row, screenPosStart.column,
11229
+ screenPosEnd.row, screenPosEnd.column
11230
+ );
11231
+ };
11232
+ this.moveBy = function(row, column) {
11233
+ this.start.row += row;
11234
+ this.start.column += column;
11235
+ this.end.row += row;
11236
+ this.end.column += column;
11237
+ };
11238
+
11239
+ }).call(Range.prototype);
11240
+ Range.fromPoints = function(start, end) {
11241
+ return new Range(start.row, start.column, end.row, end.column);
11242
+ };
11243
+ Range.comparePoints = comparePoints;
11244
+
11245
+ Range.comparePoints = function(p1, p2) {
11246
+ return p1.row - p2.row || p1.column - p2.column;
11247
+ };
11248
+
11249
+
11250
+ exports.Range = Range;
11251
+ });
11252
+
11253
+ ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(acequire, exports, module) {
11254
+ "use strict";
11255
+
11256
+ var oop = acequire("./lib/oop");
11257
+ var lang = acequire("./lib/lang");
11258
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
11259
+ var Range = acequire("./range").Range;
11260
+ var Selection = function(session) {
11261
+ this.session = session;
11262
+ this.doc = session.getDocument();
11263
+
11264
+ this.clearSelection();
11265
+ this.lead = this.selectionLead = this.doc.createAnchor(0, 0);
11266
+ this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0);
11267
+
11268
+ var self = this;
11269
+ this.lead.on("change", function(e) {
11270
+ self._emit("changeCursor");
11271
+ if (!self.$isEmpty)
11272
+ self._emit("changeSelection");
11273
+ if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
11274
+ self.$desiredColumn = null;
11275
+ });
11276
+
11277
+ this.selectionAnchor.on("change", function() {
11278
+ if (!self.$isEmpty)
11279
+ self._emit("changeSelection");
11280
+ });
11281
+ };
11282
+
11283
+ (function() {
11284
+
11285
+ oop.implement(this, EventEmitter);
11286
+ this.isEmpty = function() {
11287
+ return (this.$isEmpty || (
11288
+ this.anchor.row == this.lead.row &&
11289
+ this.anchor.column == this.lead.column
11290
+ ));
11291
+ };
11292
+ this.isMultiLine = function() {
11293
+ if (this.isEmpty()) {
11294
+ return false;
11295
+ }
11296
+
11297
+ return this.getRange().isMultiLine();
11298
+ };
11299
+ this.getCursor = function() {
11300
+ return this.lead.getPosition();
11301
+ };
11302
+ this.setSelectionAnchor = function(row, column) {
11303
+ this.anchor.setPosition(row, column);
11304
+
11305
+ if (this.$isEmpty) {
11306
+ this.$isEmpty = false;
11307
+ this._emit("changeSelection");
11308
+ }
11309
+ };
11310
+ this.getSelectionAnchor = function() {
11311
+ if (this.$isEmpty)
11312
+ return this.getSelectionLead();
11313
+ else
11314
+ return this.anchor.getPosition();
11315
+ };
11316
+ this.getSelectionLead = function() {
11317
+ return this.lead.getPosition();
11318
+ };
11319
+ this.shiftSelection = function(columns) {
11320
+ if (this.$isEmpty) {
11321
+ this.moveCursorTo(this.lead.row, this.lead.column + columns);
11322
+ return;
11323
+ }
11324
+
11325
+ var anchor = this.getSelectionAnchor();
11326
+ var lead = this.getSelectionLead();
11327
+
11328
+ var isBackwards = this.isBackwards();
11329
+
11330
+ if (!isBackwards || anchor.column !== 0)
11331
+ this.setSelectionAnchor(anchor.row, anchor.column + columns);
11332
+
11333
+ if (isBackwards || lead.column !== 0) {
11334
+ this.$moveSelection(function() {
11335
+ this.moveCursorTo(lead.row, lead.column + columns);
11336
+ });
11337
+ }
11338
+ };
11339
+ this.isBackwards = function() {
11340
+ var anchor = this.anchor;
11341
+ var lead = this.lead;
11342
+ return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
11343
+ };
11344
+ this.getRange = function() {
11345
+ var anchor = this.anchor;
11346
+ var lead = this.lead;
11347
+
11348
+ if (this.isEmpty())
11349
+ return Range.fromPoints(lead, lead);
11350
+
11351
+ if (this.isBackwards()) {
11352
+ return Range.fromPoints(lead, anchor);
11353
+ }
11354
+ else {
11355
+ return Range.fromPoints(anchor, lead);
11356
+ }
11357
+ };
11358
+ this.clearSelection = function() {
11359
+ if (!this.$isEmpty) {
11360
+ this.$isEmpty = true;
11361
+ this._emit("changeSelection");
11362
+ }
11363
+ };
11364
+ this.selectAll = function() {
11365
+ var lastRow = this.doc.getLength() - 1;
11366
+ this.setSelectionAnchor(0, 0);
11367
+ this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length);
11368
+ };
11369
+ this.setRange =
11370
+ this.setSelectionRange = function(range, reverse) {
11371
+ if (reverse) {
11372
+ this.setSelectionAnchor(range.end.row, range.end.column);
11373
+ this.selectTo(range.start.row, range.start.column);
11374
+ } else {
11375
+ this.setSelectionAnchor(range.start.row, range.start.column);
11376
+ this.selectTo(range.end.row, range.end.column);
11377
+ }
11378
+ if (this.getRange().isEmpty())
11379
+ this.$isEmpty = true;
11380
+ this.$desiredColumn = null;
11381
+ };
11382
+
11383
+ this.$moveSelection = function(mover) {
11384
+ var lead = this.lead;
11385
+ if (this.$isEmpty)
11386
+ this.setSelectionAnchor(lead.row, lead.column);
11387
+
11388
+ mover.call(this);
11389
+ };
11390
+ this.selectTo = function(row, column) {
11391
+ this.$moveSelection(function() {
11392
+ this.moveCursorTo(row, column);
11393
+ });
11394
+ };
11395
+ this.selectToPosition = function(pos) {
11396
+ this.$moveSelection(function() {
11397
+ this.moveCursorToPosition(pos);
11398
+ });
11399
+ };
11400
+ this.moveTo = function(row, column) {
11401
+ this.clearSelection();
11402
+ this.moveCursorTo(row, column);
11403
+ };
11404
+ this.moveToPosition = function(pos) {
11405
+ this.clearSelection();
11406
+ this.moveCursorToPosition(pos);
11407
+ };
11408
+ this.selectUp = function() {
11409
+ this.$moveSelection(this.moveCursorUp);
11410
+ };
11411
+ this.selectDown = function() {
11412
+ this.$moveSelection(this.moveCursorDown);
11413
+ };
11414
+ this.selectRight = function() {
11415
+ this.$moveSelection(this.moveCursorRight);
11416
+ };
11417
+ this.selectLeft = function() {
11418
+ this.$moveSelection(this.moveCursorLeft);
11419
+ };
11420
+ this.selectLineStart = function() {
11421
+ this.$moveSelection(this.moveCursorLineStart);
11422
+ };
11423
+ this.selectLineEnd = function() {
11424
+ this.$moveSelection(this.moveCursorLineEnd);
11425
+ };
11426
+ this.selectFileEnd = function() {
11427
+ this.$moveSelection(this.moveCursorFileEnd);
11428
+ };
11429
+ this.selectFileStart = function() {
11430
+ this.$moveSelection(this.moveCursorFileStart);
11431
+ };
11432
+ this.selectWordRight = function() {
11433
+ this.$moveSelection(this.moveCursorWordRight);
11434
+ };
11435
+ this.selectWordLeft = function() {
11436
+ this.$moveSelection(this.moveCursorWordLeft);
11437
+ };
11438
+ this.getWordRange = function(row, column) {
11439
+ if (typeof column == "undefined") {
11440
+ var cursor = row || this.lead;
11441
+ row = cursor.row;
11442
+ column = cursor.column;
11443
+ }
11444
+ return this.session.getWordRange(row, column);
11445
+ };
11446
+ this.selectWord = function() {
11447
+ this.setSelectionRange(this.getWordRange());
11448
+ };
11449
+ this.selectAWord = function() {
11450
+ var cursor = this.getCursor();
11451
+ var range = this.session.getAWordRange(cursor.row, cursor.column);
11452
+ this.setSelectionRange(range);
11453
+ };
11454
+
11455
+ this.getLineRange = function(row, excludeLastChar) {
11456
+ var rowStart = typeof row == "number" ? row : this.lead.row;
11457
+ var rowEnd;
11458
+
11459
+ var foldLine = this.session.getFoldLine(rowStart);
11460
+ if (foldLine) {
11461
+ rowStart = foldLine.start.row;
11462
+ rowEnd = foldLine.end.row;
11463
+ } else {
11464
+ rowEnd = rowStart;
11465
+ }
11466
+ if (excludeLastChar === true)
11467
+ return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length);
11468
+ else
11469
+ return new Range(rowStart, 0, rowEnd + 1, 0);
11470
+ };
11471
+ this.selectLine = function() {
11472
+ this.setSelectionRange(this.getLineRange());
11473
+ };
11474
+ this.moveCursorUp = function() {
11475
+ this.moveCursorBy(-1, 0);
11476
+ };
11477
+ this.moveCursorDown = function() {
11478
+ this.moveCursorBy(1, 0);
11479
+ };
11480
+ this.moveCursorLeft = function() {
11481
+ var cursor = this.lead.getPosition(),
11482
+ fold;
11483
+
11484
+ if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {
11485
+ this.moveCursorTo(fold.start.row, fold.start.column);
11486
+ } else if (cursor.column === 0) {
11487
+ if (cursor.row > 0) {
11488
+ this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length);
11489
+ }
11490
+ }
11491
+ else {
11492
+ var tabSize = this.session.getTabSize();
11493
+ if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize)
11494
+ this.moveCursorBy(0, -tabSize);
11495
+ else
11496
+ this.moveCursorBy(0, -1);
11497
+ }
11498
+ };
11499
+ this.moveCursorRight = function() {
11500
+ var cursor = this.lead.getPosition(),
11501
+ fold;
11502
+ if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
11503
+ this.moveCursorTo(fold.end.row, fold.end.column);
11504
+ }
11505
+ else if (this.lead.column == this.doc.getLine(this.lead.row).length) {
11506
+ if (this.lead.row < this.doc.getLength() - 1) {
11507
+ this.moveCursorTo(this.lead.row + 1, 0);
11508
+ }
11509
+ }
11510
+ else {
11511
+ var tabSize = this.session.getTabSize();
11512
+ var cursor = this.lead;
11513
+ if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize)
11514
+ this.moveCursorBy(0, tabSize);
11515
+ else
11516
+ this.moveCursorBy(0, 1);
11517
+ }
11518
+ };
11519
+ this.moveCursorLineStart = function() {
11520
+ var row = this.lead.row;
11521
+ var column = this.lead.column;
11522
+ var screenRow = this.session.documentToScreenRow(row, column);
11523
+ var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);
11524
+ var beforeCursor = this.session.getDisplayLine(
11525
+ row, null, firstColumnPosition.row,
11526
+ firstColumnPosition.column
11527
+ );
11528
+
11529
+ var leadingSpace = beforeCursor.match(/^\s*/);
11530
+ if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart)
11531
+ firstColumnPosition.column += leadingSpace[0].length;
11532
+ this.moveCursorToPosition(firstColumnPosition);
11533
+ };
11534
+ this.moveCursorLineEnd = function() {
11535
+ var lead = this.lead;
11536
+ var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
11537
+ if (this.lead.column == lineEnd.column) {
11538
+ var line = this.session.getLine(lineEnd.row);
11539
+ if (lineEnd.column == line.length) {
11540
+ var textEnd = line.search(/\s+$/);
11541
+ if (textEnd > 0)
11542
+ lineEnd.column = textEnd;
11543
+ }
11544
+ }
11545
+
11546
+ this.moveCursorTo(lineEnd.row, lineEnd.column);
11547
+ };
11548
+ this.moveCursorFileEnd = function() {
11549
+ var row = this.doc.getLength() - 1;
11550
+ var column = this.doc.getLine(row).length;
11551
+ this.moveCursorTo(row, column);
11552
+ };
11553
+ this.moveCursorFileStart = function() {
11554
+ this.moveCursorTo(0, 0);
11555
+ };
11556
+ this.moveCursorLongWordRight = function() {
11557
+ var row = this.lead.row;
11558
+ var column = this.lead.column;
11559
+ var line = this.doc.getLine(row);
11560
+ var rightOfCursor = line.substring(column);
11561
+
11562
+ var match;
11563
+ this.session.nonTokenRe.lastIndex = 0;
11564
+ this.session.tokenRe.lastIndex = 0;
11565
+ var fold = this.session.getFoldAt(row, column, 1);
11566
+ if (fold) {
11567
+ this.moveCursorTo(fold.end.row, fold.end.column);
11568
+ return;
11569
+ }
11570
+ if (match = this.session.nonTokenRe.exec(rightOfCursor)) {
11571
+ column += this.session.nonTokenRe.lastIndex;
11572
+ this.session.nonTokenRe.lastIndex = 0;
11573
+ rightOfCursor = line.substring(column);
11574
+ }
11575
+ if (column >= line.length) {
11576
+ this.moveCursorTo(row, line.length);
11577
+ this.moveCursorRight();
11578
+ if (row < this.doc.getLength() - 1)
11579
+ this.moveCursorWordRight();
11580
+ return;
11581
+ }
11582
+ if (match = this.session.tokenRe.exec(rightOfCursor)) {
11583
+ column += this.session.tokenRe.lastIndex;
11584
+ this.session.tokenRe.lastIndex = 0;
11585
+ }
11586
+
11587
+ this.moveCursorTo(row, column);
11588
+ };
11589
+ this.moveCursorLongWordLeft = function() {
11590
+ var row = this.lead.row;
11591
+ var column = this.lead.column;
11592
+ var fold;
11593
+ if (fold = this.session.getFoldAt(row, column, -1)) {
11594
+ this.moveCursorTo(fold.start.row, fold.start.column);
11595
+ return;
11596
+ }
11597
+
11598
+ var str = this.session.getFoldStringAt(row, column, -1);
11599
+ if (str == null) {
11600
+ str = this.doc.getLine(row).substring(0, column);
11601
+ }
11602
+
11603
+ var leftOfCursor = lang.stringReverse(str);
11604
+ var match;
11605
+ this.session.nonTokenRe.lastIndex = 0;
11606
+ this.session.tokenRe.lastIndex = 0;
11607
+ if (match = this.session.nonTokenRe.exec(leftOfCursor)) {
11608
+ column -= this.session.nonTokenRe.lastIndex;
11609
+ leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);
11610
+ this.session.nonTokenRe.lastIndex = 0;
11611
+ }
11612
+ if (column <= 0) {
11613
+ this.moveCursorTo(row, 0);
11614
+ this.moveCursorLeft();
11615
+ if (row > 0)
11616
+ this.moveCursorWordLeft();
11617
+ return;
11618
+ }
11619
+ if (match = this.session.tokenRe.exec(leftOfCursor)) {
11620
+ column -= this.session.tokenRe.lastIndex;
11621
+ this.session.tokenRe.lastIndex = 0;
11622
+ }
11623
+
11624
+ this.moveCursorTo(row, column);
11625
+ };
11626
+
11627
+ this.$shortWordEndIndex = function(rightOfCursor) {
11628
+ var match, index = 0, ch;
11629
+ var whitespaceRe = /\s/;
11630
+ var tokenRe = this.session.tokenRe;
11631
+
11632
+ tokenRe.lastIndex = 0;
11633
+ if (match = this.session.tokenRe.exec(rightOfCursor)) {
11634
+ index = this.session.tokenRe.lastIndex;
11635
+ } else {
11636
+ while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
11637
+ index ++;
11638
+
11639
+ if (index < 1) {
11640
+ tokenRe.lastIndex = 0;
11641
+ while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) {
11642
+ tokenRe.lastIndex = 0;
11643
+ index ++;
11644
+ if (whitespaceRe.test(ch)) {
11645
+ if (index > 2) {
11646
+ index--;
11647
+ break;
11648
+ } else {
11649
+ while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
11650
+ index ++;
11651
+ if (index > 2)
11652
+ break;
11653
+ }
11654
+ }
11655
+ }
11656
+ }
11657
+ }
11658
+ tokenRe.lastIndex = 0;
11659
+
11660
+ return index;
11661
+ };
11662
+
11663
+ this.moveCursorShortWordRight = function() {
11664
+ var row = this.lead.row;
11665
+ var column = this.lead.column;
11666
+ var line = this.doc.getLine(row);
11667
+ var rightOfCursor = line.substring(column);
11668
+
11669
+ var fold = this.session.getFoldAt(row, column, 1);
11670
+ if (fold)
11671
+ return this.moveCursorTo(fold.end.row, fold.end.column);
11672
+
11673
+ if (column == line.length) {
11674
+ var l = this.doc.getLength();
11675
+ do {
11676
+ row++;
11677
+ rightOfCursor = this.doc.getLine(row);
11678
+ } while (row < l && /^\s*$/.test(rightOfCursor));
11679
+
11680
+ if (!/^\s+/.test(rightOfCursor))
11681
+ rightOfCursor = "";
11682
+ column = 0;
11683
+ }
11684
+
11685
+ var index = this.$shortWordEndIndex(rightOfCursor);
11686
+
11687
+ this.moveCursorTo(row, column + index);
11688
+ };
11689
+
11690
+ this.moveCursorShortWordLeft = function() {
11691
+ var row = this.lead.row;
11692
+ var column = this.lead.column;
11693
+
11694
+ var fold;
11695
+ if (fold = this.session.getFoldAt(row, column, -1))
11696
+ return this.moveCursorTo(fold.start.row, fold.start.column);
11697
+
11698
+ var line = this.session.getLine(row).substring(0, column);
11699
+ if (column === 0) {
11700
+ do {
11701
+ row--;
11702
+ line = this.doc.getLine(row);
11703
+ } while (row > 0 && /^\s*$/.test(line));
11704
+
11705
+ column = line.length;
11706
+ if (!/\s+$/.test(line))
11707
+ line = "";
11708
+ }
11709
+
11710
+ var leftOfCursor = lang.stringReverse(line);
11711
+ var index = this.$shortWordEndIndex(leftOfCursor);
11712
+
11713
+ return this.moveCursorTo(row, column - index);
11714
+ };
11715
+
11716
+ this.moveCursorWordRight = function() {
11717
+ if (this.session.$selectLongWords)
11718
+ this.moveCursorLongWordRight();
11719
+ else
11720
+ this.moveCursorShortWordRight();
11721
+ };
11722
+
11723
+ this.moveCursorWordLeft = function() {
11724
+ if (this.session.$selectLongWords)
11725
+ this.moveCursorLongWordLeft();
11726
+ else
11727
+ this.moveCursorShortWordLeft();
11728
+ };
11729
+ this.moveCursorBy = function(rows, chars) {
11730
+ var screenPos = this.session.documentToScreenPosition(
11731
+ this.lead.row,
11732
+ this.lead.column
11733
+ );
11734
+
11735
+ if (chars === 0) {
11736
+ if (this.$desiredColumn)
11737
+ screenPos.column = this.$desiredColumn;
11738
+ else
11739
+ this.$desiredColumn = screenPos.column;
11740
+ }
11741
+
11742
+ var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);
11743
+
11744
+ if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) {
11745
+ if (this.session.lineWidgets && this.session.lineWidgets[docPos.row])
11746
+ docPos.row++;
11747
+ }
11748
+ this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
11749
+ };
11750
+ this.moveCursorToPosition = function(position) {
11751
+ this.moveCursorTo(position.row, position.column);
11752
+ };
11753
+ this.moveCursorTo = function(row, column, keepDesiredColumn) {
11754
+ var fold = this.session.getFoldAt(row, column, 1);
11755
+ if (fold) {
11756
+ row = fold.start.row;
11757
+ column = fold.start.column;
11758
+ }
11759
+
11760
+ this.$keepDesiredColumnOnChange = true;
11761
+ this.lead.setPosition(row, column);
11762
+ this.$keepDesiredColumnOnChange = false;
11763
+
11764
+ if (!keepDesiredColumn)
11765
+ this.$desiredColumn = null;
11766
+ };
11767
+ this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
11768
+ var pos = this.session.screenToDocumentPosition(row, column);
11769
+ this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
11770
+ };
11771
+ this.detach = function() {
11772
+ this.lead.detach();
11773
+ this.anchor.detach();
11774
+ this.session = this.doc = null;
11775
+ };
11776
+
11777
+ this.fromOrientedRange = function(range) {
11778
+ this.setSelectionRange(range, range.cursor == range.start);
11779
+ this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
11780
+ };
11781
+
11782
+ this.toOrientedRange = function(range) {
11783
+ var r = this.getRange();
11784
+ if (range) {
11785
+ range.start.column = r.start.column;
11786
+ range.start.row = r.start.row;
11787
+ range.end.column = r.end.column;
11788
+ range.end.row = r.end.row;
11789
+ } else {
11790
+ range = r;
11791
+ }
11792
+
11793
+ range.cursor = this.isBackwards() ? range.start : range.end;
11794
+ range.desiredColumn = this.$desiredColumn;
11795
+ return range;
11796
+ };
11797
+ this.getRangeOfMovements = function(func) {
11798
+ var start = this.getCursor();
11799
+ try {
11800
+ func.call(null, this);
11801
+ var end = this.getCursor();
11802
+ return Range.fromPoints(start,end);
11803
+ } catch(e) {
11804
+ return Range.fromPoints(start,start);
11805
+ } finally {
11806
+ this.moveCursorToPosition(start);
11807
+ }
11808
+ };
11809
+
11810
+ this.toJSON = function() {
11811
+ if (this.rangeCount) {
11812
+ var data = this.ranges.map(function(r) {
11813
+ var r1 = r.clone();
11814
+ r1.isBackwards = r.cursor == r.start;
11815
+ return r1;
11816
+ });
11817
+ } else {
11818
+ var data = this.getRange();
11819
+ data.isBackwards = this.isBackwards();
11820
+ }
11821
+ return data;
11822
+ };
11823
+
11824
+ this.fromJSON = function(data) {
11825
+ if (data.start == undefined) {
11826
+ if (this.rangeList) {
11827
+ this.toSingleRange(data[0]);
11828
+ for (var i = data.length; i--; ) {
11829
+ var r = Range.fromPoints(data[i].start, data[i].end);
11830
+ if (data.isBackwards)
11831
+ r.cursor = r.start;
11832
+ this.addRange(r, true);
11833
+ }
11834
+ return;
11835
+ } else
11836
+ data = data[0];
11837
+ }
11838
+ if (this.rangeList)
11839
+ this.toSingleRange(data);
11840
+ this.setSelectionRange(data, data.isBackwards);
11841
+ };
11842
+
11843
+ this.isEqual = function(data) {
11844
+ if ((data.length || this.rangeCount) && data.length != this.rangeCount)
11845
+ return false;
11846
+ if (!data.length || !this.ranges)
11847
+ return this.getRange().isEqual(data);
11848
+
11849
+ for (var i = this.ranges.length; i--; ) {
11850
+ if (!this.ranges[i].isEqual(data[i]))
11851
+ return false;
11852
+ }
11853
+ return true;
11854
+ };
11855
+
11856
+ }).call(Selection.prototype);
11857
+
11858
+ exports.Selection = Selection;
11859
+ });
11860
+
11861
+ ace.define("ace/tokenizer",["require","exports","module"], function(acequire, exports, module) {
11862
+ "use strict";
11863
+ var MAX_TOKEN_COUNT = 2000;
11864
+ var Tokenizer = function(rules) {
11865
+ this.states = rules;
11866
+
11867
+ this.regExps = {};
11868
+ this.matchMappings = {};
11869
+ for (var key in this.states) {
11870
+ var state = this.states[key];
11871
+ var ruleRegExps = [];
11872
+ var matchTotal = 0;
11873
+ var mapping = this.matchMappings[key] = {defaultToken: "text"};
11874
+ var flag = "g";
11875
+
11876
+ var splitterRurles = [];
11877
+ for (var i = 0; i < state.length; i++) {
11878
+ var rule = state[i];
11879
+ if (rule.defaultToken)
11880
+ mapping.defaultToken = rule.defaultToken;
11881
+ if (rule.caseInsensitive)
11882
+ flag = "gi";
11883
+ if (rule.regex == null)
11884
+ continue;
11885
+
11886
+ if (rule.regex instanceof RegExp)
11887
+ rule.regex = rule.regex.toString().slice(1, -1);
11888
+ var adjustedregex = rule.regex;
11889
+ var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2;
11890
+ if (Array.isArray(rule.token)) {
11891
+ if (rule.token.length == 1 || matchcount == 1) {
11892
+ rule.token = rule.token[0];
11893
+ } else if (matchcount - 1 != rule.token.length) {
11894
+ this.reportError("number of classes and regexp groups doesn't match", {
11895
+ rule: rule,
11896
+ groupCount: matchcount - 1
11897
+ });
11898
+ rule.token = rule.token[0];
11899
+ } else {
11900
+ rule.tokenArray = rule.token;
11901
+ rule.token = null;
11902
+ rule.onMatch = this.$arrayTokens;
11903
+ }
11904
+ } else if (typeof rule.token == "function" && !rule.onMatch) {
11905
+ if (matchcount > 1)
11906
+ rule.onMatch = this.$applyToken;
11907
+ else
11908
+ rule.onMatch = rule.token;
11909
+ }
11910
+
11911
+ if (matchcount > 1) {
11912
+ if (/\\\d/.test(rule.regex)) {
11913
+ adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) {
11914
+ return "\\" + (parseInt(digit, 10) + matchTotal + 1);
11915
+ });
11916
+ } else {
11917
+ matchcount = 1;
11918
+ adjustedregex = this.removeCapturingGroups(rule.regex);
11919
+ }
11920
+ if (!rule.splitRegex && typeof rule.token != "string")
11921
+ splitterRurles.push(rule); // flag will be known only at the very end
11922
+ }
11923
+
11924
+ mapping[matchTotal] = i;
11925
+ matchTotal += matchcount;
11926
+
11927
+ ruleRegExps.push(adjustedregex);
11928
+ if (!rule.onMatch)
11929
+ rule.onMatch = null;
11930
+ }
11931
+
11932
+ if (!ruleRegExps.length) {
11933
+ mapping[0] = 0;
11934
+ ruleRegExps.push("$");
11935
+ }
11936
+
11937
+ splitterRurles.forEach(function(rule) {
11938
+ rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);
11939
+ }, this);
11940
+
11941
+ this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag);
11942
+ }
11943
+ };
11944
+
11945
+ (function() {
11946
+ this.$setMaxTokenCount = function(m) {
11947
+ MAX_TOKEN_COUNT = m | 0;
11948
+ };
11949
+
11950
+ this.$applyToken = function(str) {
11951
+ var values = this.splitRegex.exec(str).slice(1);
11952
+ var types = this.token.apply(this, values);
11953
+ if (typeof types === "string")
11954
+ return [{type: types, value: str}];
11955
+
11956
+ var tokens = [];
11957
+ for (var i = 0, l = types.length; i < l; i++) {
11958
+ if (values[i])
11959
+ tokens[tokens.length] = {
11960
+ type: types[i],
11961
+ value: values[i]
11962
+ };
11963
+ }
11964
+ return tokens;
11965
+ },
11966
+
11967
+ this.$arrayTokens = function(str) {
11968
+ if (!str)
11969
+ return [];
11970
+ var values = this.splitRegex.exec(str);
11971
+ if (!values)
11972
+ return "text";
11973
+ var tokens = [];
11974
+ var types = this.tokenArray;
11975
+ for (var i = 0, l = types.length; i < l; i++) {
11976
+ if (values[i + 1])
11977
+ tokens[tokens.length] = {
11978
+ type: types[i],
11979
+ value: values[i + 1]
11980
+ };
11981
+ }
11982
+ return tokens;
11983
+ };
11984
+
11985
+ this.removeCapturingGroups = function(src) {
11986
+ var r = src.replace(
11987
+ /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,
11988
+ function(x, y) {return y ? "(?:" : x;}
11989
+ );
11990
+ return r;
11991
+ };
11992
+
11993
+ this.createSplitterRegexp = function(src, flag) {
11994
+ if (src.indexOf("(?=") != -1) {
11995
+ var stack = 0;
11996
+ var inChClass = false;
11997
+ var lastCapture = {};
11998
+ src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function(
11999
+ m, esc, parenOpen, parenClose, square, index
12000
+ ) {
12001
+ if (inChClass) {
12002
+ inChClass = square != "]";
12003
+ } else if (square) {
12004
+ inChClass = true;
12005
+ } else if (parenClose) {
12006
+ if (stack == lastCapture.stack) {
12007
+ lastCapture.end = index+1;
12008
+ lastCapture.stack = -1;
12009
+ }
12010
+ stack--;
12011
+ } else if (parenOpen) {
12012
+ stack++;
12013
+ if (parenOpen.length != 1) {
12014
+ lastCapture.stack = stack
12015
+ lastCapture.start = index;
12016
+ }
12017
+ }
12018
+ return m;
12019
+ });
12020
+
12021
+ if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end)))
12022
+ src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
12023
+ }
12024
+ return new RegExp(src, (flag||"").replace("g", ""));
12025
+ };
12026
+ this.getLineTokens = function(line, startState) {
12027
+ if (startState && typeof startState != "string") {
12028
+ var stack = startState.slice(0);
12029
+ startState = stack[0];
12030
+ if (startState === "#tmp") {
12031
+ stack.shift()
12032
+ startState = stack.shift()
12033
+ }
12034
+ } else
12035
+ var stack = [];
12036
+
12037
+ var currentState = startState || "start";
12038
+ var state = this.states[currentState];
12039
+ if (!state) {
12040
+ currentState = "start";
12041
+ state = this.states[currentState];
12042
+ }
12043
+ var mapping = this.matchMappings[currentState];
12044
+ var re = this.regExps[currentState];
12045
+ re.lastIndex = 0;
12046
+
12047
+ var match, tokens = [];
12048
+ var lastIndex = 0;
12049
+ var matchAttempts = 0;
12050
+
12051
+ var token = {type: null, value: ""};
12052
+
12053
+ while (match = re.exec(line)) {
12054
+ var type = mapping.defaultToken;
12055
+ var rule = null;
12056
+ var value = match[0];
12057
+ var index = re.lastIndex;
12058
+
12059
+ if (index - value.length > lastIndex) {
12060
+ var skipped = line.substring(lastIndex, index - value.length);
12061
+ if (token.type == type) {
12062
+ token.value += skipped;
12063
+ } else {
12064
+ if (token.type)
12065
+ tokens.push(token);
12066
+ token = {type: type, value: skipped};
12067
+ }
12068
+ }
12069
+
12070
+ for (var i = 0; i < match.length-2; i++) {
12071
+ if (match[i + 1] === undefined)
12072
+ continue;
12073
+
12074
+ rule = state[mapping[i]];
12075
+
12076
+ if (rule.onMatch)
12077
+ type = rule.onMatch(value, currentState, stack);
12078
+ else
12079
+ type = rule.token;
12080
+
12081
+ if (rule.next) {
12082
+ if (typeof rule.next == "string") {
12083
+ currentState = rule.next;
12084
+ } else {
12085
+ currentState = rule.next(currentState, stack);
12086
+ }
12087
+
12088
+ state = this.states[currentState];
12089
+ if (!state) {
12090
+ this.reportError("state doesn't exist", currentState);
12091
+ currentState = "start";
12092
+ state = this.states[currentState];
12093
+ }
12094
+ mapping = this.matchMappings[currentState];
12095
+ lastIndex = index;
12096
+ re = this.regExps[currentState];
12097
+ re.lastIndex = index;
12098
+ }
12099
+ break;
12100
+ }
12101
+
12102
+ if (value) {
12103
+ if (typeof type === "string") {
12104
+ if ((!rule || rule.merge !== false) && token.type === type) {
12105
+ token.value += value;
12106
+ } else {
12107
+ if (token.type)
12108
+ tokens.push(token);
12109
+ token = {type: type, value: value};
12110
+ }
12111
+ } else if (type) {
12112
+ if (token.type)
12113
+ tokens.push(token);
12114
+ token = {type: null, value: ""};
12115
+ for (var i = 0; i < type.length; i++)
12116
+ tokens.push(type[i]);
12117
+ }
12118
+ }
12119
+
12120
+ if (lastIndex == line.length)
12121
+ break;
12122
+
12123
+ lastIndex = index;
12124
+
12125
+ if (matchAttempts++ > MAX_TOKEN_COUNT) {
12126
+ if (matchAttempts > 2 * line.length) {
12127
+ this.reportError("infinite loop with in ace tokenizer", {
12128
+ startState: startState,
12129
+ line: line
12130
+ });
12131
+ }
12132
+ while (lastIndex < line.length) {
12133
+ if (token.type)
12134
+ tokens.push(token);
12135
+ token = {
12136
+ value: line.substring(lastIndex, lastIndex += 2000),
12137
+ type: "overflow"
12138
+ };
12139
+ }
12140
+ currentState = "start";
12141
+ stack = [];
12142
+ break;
12143
+ }
12144
+ }
12145
+
12146
+ if (token.type)
12147
+ tokens.push(token);
12148
+
12149
+ if (stack.length > 1) {
12150
+ if (stack[0] !== currentState)
12151
+ stack.unshift("#tmp", currentState);
12152
+ }
12153
+ return {
12154
+ tokens : tokens,
12155
+ state : stack.length ? stack : currentState
12156
+ };
12157
+ };
12158
+
12159
+ this.reportError = function(msg, data) {
12160
+ var e = new Error(msg);
12161
+ e.data = data;
12162
+ if (typeof console == "object" && console.error)
12163
+ console.error(e);
12164
+ setTimeout(function() { throw e; });
12165
+ };
12166
+ }).call(Tokenizer.prototype);
12167
+
12168
+ exports.Tokenizer = Tokenizer;
12169
+ });
12170
+
12171
+ ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(acequire, exports, module) {
12172
+ "use strict";
12173
+
12174
+ var lang = acequire("../lib/lang");
12175
+
12176
+ var TextHighlightRules = function() {
12177
+
12178
+ this.$rules = {
12179
+ "start" : [{
12180
+ token : "empty_line",
12181
+ regex : '^$'
12182
+ }, {
12183
+ defaultToken : "text"
12184
+ }]
12185
+ };
12186
+ };
12187
+
12188
+ (function() {
12189
+
12190
+ this.addRules = function(rules, prefix) {
12191
+ if (!prefix) {
12192
+ for (var key in rules)
12193
+ this.$rules[key] = rules[key];
12194
+ return;
12195
+ }
12196
+ for (var key in rules) {
12197
+ var state = rules[key];
12198
+ for (var i = 0; i < state.length; i++) {
12199
+ var rule = state[i];
12200
+ if (rule.next || rule.onMatch) {
12201
+ if (typeof rule.next != "string") {
12202
+ if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
12203
+ rule.nextState = prefix + rule.nextState;
12204
+ } else {
12205
+ if (rule.next.indexOf(prefix) !== 0)
12206
+ rule.next = prefix + rule.next;
12207
+ }
12208
+ }
12209
+ }
12210
+ this.$rules[prefix + key] = state;
12211
+ }
12212
+ };
12213
+
12214
+ this.getRules = function() {
12215
+ return this.$rules;
12216
+ };
12217
+
12218
+ this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {
12219
+ var embedRules = typeof HighlightRules == "function"
12220
+ ? new HighlightRules().getRules()
12221
+ : HighlightRules;
12222
+ if (states) {
12223
+ for (var i = 0; i < states.length; i++)
12224
+ states[i] = prefix + states[i];
12225
+ } else {
12226
+ states = [];
12227
+ for (var key in embedRules)
12228
+ states.push(prefix + key);
12229
+ }
12230
+
12231
+ this.addRules(embedRules, prefix);
12232
+
12233
+ if (escapeRules) {
12234
+ var addRules = Array.prototype[append ? "push" : "unshift"];
12235
+ for (var i = 0; i < states.length; i++)
12236
+ addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
12237
+ }
12238
+
12239
+ if (!this.$embeds)
12240
+ this.$embeds = [];
12241
+ this.$embeds.push(prefix);
12242
+ };
12243
+
12244
+ this.getEmbeds = function() {
12245
+ return this.$embeds;
12246
+ };
12247
+
12248
+ var pushState = function(currentState, stack) {
12249
+ if (currentState != "start" || stack.length)
12250
+ stack.unshift(this.nextState, currentState);
12251
+ return this.nextState;
12252
+ };
12253
+ var popState = function(currentState, stack) {
12254
+ stack.shift();
12255
+ return stack.shift() || "start";
12256
+ };
12257
+
12258
+ this.normalizeRules = function() {
12259
+ var id = 0;
12260
+ var rules = this.$rules;
12261
+ function processState(key) {
12262
+ var state = rules[key];
12263
+ state.processed = true;
12264
+ for (var i = 0; i < state.length; i++) {
12265
+ var rule = state[i];
12266
+ if (!rule.regex && rule.start) {
12267
+ rule.regex = rule.start;
12268
+ if (!rule.next)
12269
+ rule.next = [];
12270
+ rule.next.push({
12271
+ defaultToken: rule.token
12272
+ }, {
12273
+ token: rule.token + ".end",
12274
+ regex: rule.end || rule.start,
12275
+ next: "pop"
12276
+ });
12277
+ rule.token = rule.token + ".start";
12278
+ rule.push = true;
12279
+ }
12280
+ var next = rule.next || rule.push;
12281
+ if (next && Array.isArray(next)) {
12282
+ var stateName = rule.stateName;
12283
+ if (!stateName) {
12284
+ stateName = rule.token;
12285
+ if (typeof stateName != "string")
12286
+ stateName = stateName[0] || "";
12287
+ if (rules[stateName])
12288
+ stateName += id++;
12289
+ }
12290
+ rules[stateName] = next;
12291
+ rule.next = stateName;
12292
+ processState(stateName);
12293
+ } else if (next == "pop") {
12294
+ rule.next = popState;
12295
+ }
12296
+
12297
+ if (rule.push) {
12298
+ rule.nextState = rule.next || rule.push;
12299
+ rule.next = pushState;
12300
+ delete rule.push;
12301
+ }
12302
+
12303
+ if (rule.rules) {
12304
+ for (var r in rule.rules) {
12305
+ if (rules[r]) {
12306
+ if (rules[r].push)
12307
+ rules[r].push.apply(rules[r], rule.rules[r]);
12308
+ } else {
12309
+ rules[r] = rule.rules[r];
12310
+ }
12311
+ }
12312
+ }
12313
+ if (rule.include || typeof rule == "string") {
12314
+ var includeName = rule.include || rule;
12315
+ var toInsert = rules[includeName];
12316
+ } else if (Array.isArray(rule))
12317
+ toInsert = rule;
12318
+
12319
+ if (toInsert) {
12320
+ var args = [i, 1].concat(toInsert);
12321
+ if (rule.noEscape)
12322
+ args = args.filter(function(x) {return !x.next;});
12323
+ state.splice.apply(state, args);
12324
+ i--;
12325
+ toInsert = null;
12326
+ }
12327
+
12328
+ if (rule.keywordMap) {
12329
+ rule.token = this.createKeywordMapper(
12330
+ rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive
12331
+ );
12332
+ delete rule.defaultToken;
12333
+ }
12334
+ }
12335
+ }
12336
+ Object.keys(rules).forEach(processState, this);
12337
+ };
12338
+
12339
+ this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {
12340
+ var keywords = Object.create(null);
12341
+ Object.keys(map).forEach(function(className) {
12342
+ var a = map[className];
12343
+ if (ignoreCase)
12344
+ a = a.toLowerCase();
12345
+ var list = a.split(splitChar || "|");
12346
+ for (var i = list.length; i--; )
12347
+ keywords[list[i]] = className;
12348
+ });
12349
+ if (Object.getPrototypeOf(keywords)) {
12350
+ keywords.__proto__ = null;
12351
+ }
12352
+ this.$keywordList = Object.keys(keywords);
12353
+ map = null;
12354
+ return ignoreCase
12355
+ ? function(value) {return keywords[value.toLowerCase()] || defaultToken }
12356
+ : function(value) {return keywords[value] || defaultToken };
12357
+ };
12358
+
12359
+ this.getKeywords = function() {
12360
+ return this.$keywords;
12361
+ };
12362
+
12363
+ }).call(TextHighlightRules.prototype);
12364
+
12365
+ exports.TextHighlightRules = TextHighlightRules;
12366
+ });
12367
+
12368
+ ace.define("ace/mode/behaviour",["require","exports","module"], function(acequire, exports, module) {
12369
+ "use strict";
12370
+
12371
+ var Behaviour = function() {
12372
+ this.$behaviours = {};
12373
+ };
12374
+
12375
+ (function () {
12376
+
12377
+ this.add = function (name, action, callback) {
12378
+ switch (undefined) {
12379
+ case this.$behaviours:
12380
+ this.$behaviours = {};
12381
+ case this.$behaviours[name]:
12382
+ this.$behaviours[name] = {};
12383
+ }
12384
+ this.$behaviours[name][action] = callback;
12385
+ }
12386
+
12387
+ this.addBehaviours = function (behaviours) {
12388
+ for (var key in behaviours) {
12389
+ for (var action in behaviours[key]) {
12390
+ this.add(key, action, behaviours[key][action]);
12391
+ }
12392
+ }
12393
+ }
12394
+
12395
+ this.remove = function (name) {
12396
+ if (this.$behaviours && this.$behaviours[name]) {
12397
+ delete this.$behaviours[name];
12398
+ }
12399
+ }
12400
+
12401
+ this.inherit = function (mode, filter) {
12402
+ if (typeof mode === "function") {
12403
+ var behaviours = new mode().getBehaviours(filter);
12404
+ } else {
12405
+ var behaviours = mode.getBehaviours(filter);
12406
+ }
12407
+ this.addBehaviours(behaviours);
12408
+ }
12409
+
12410
+ this.getBehaviours = function (filter) {
12411
+ if (!filter) {
12412
+ return this.$behaviours;
12413
+ } else {
12414
+ var ret = {}
12415
+ for (var i = 0; i < filter.length; i++) {
12416
+ if (this.$behaviours[filter[i]]) {
12417
+ ret[filter[i]] = this.$behaviours[filter[i]];
12418
+ }
12419
+ }
12420
+ return ret;
12421
+ }
12422
+ }
12423
+
12424
+ }).call(Behaviour.prototype);
12425
+
12426
+ exports.Behaviour = Behaviour;
12427
+ });
12428
+
12429
+ ace.define("ace/unicode",["require","exports","module"], function(acequire, exports, module) {
12430
+ "use strict";
12431
+ exports.packages = {};
12432
+
12433
+ addUnicodePackage({
12434
+ L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",
12435
+ Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",
12436
+ Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",
12437
+ Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",
12438
+ Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",
12439
+ Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",
12440
+ M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",
12441
+ Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",
12442
+ Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",
12443
+ Me: "0488048906DE20DD-20E020E2-20E4A670-A672",
12444
+ N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",
12445
+ Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",
12446
+ Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",
12447
+ No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",
12448
+ P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",
12449
+ Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",
12450
+ Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",
12451
+ Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",
12452
+ Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",
12453
+ Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21",
12454
+ Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F",
12455
+ Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",
12456
+ S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",
12457
+ Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",
12458
+ Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",
12459
+ Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",
12460
+ So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",
12461
+ Z: "002000A01680180E2000-200A20282029202F205F3000",
12462
+ Zs: "002000A01680180E2000-200A202F205F3000",
12463
+ Zl: "2028",
12464
+ Zp: "2029",
12465
+ C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",
12466
+ Cc: "0000-001F007F-009F",
12467
+ Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",
12468
+ Co: "E000-F8FF",
12469
+ Cs: "D800-DFFF",
12470
+ Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"
12471
+ });
12472
+
12473
+ function addUnicodePackage (pack) {
12474
+ var codePoint = /\w{4}/g;
12475
+ for (var name in pack)
12476
+ exports.packages[name] = pack[name].replace(codePoint, "\\u$&");
12477
+ };
12478
+
12479
+ });
12480
+
12481
+ ace.define("ace/token_iterator",["require","exports","module"], function(acequire, exports, module) {
12482
+ "use strict";
12483
+ var TokenIterator = function(session, initialRow, initialColumn) {
12484
+ this.$session = session;
12485
+ this.$row = initialRow;
12486
+ this.$rowTokens = session.getTokens(initialRow);
12487
+
12488
+ var token = session.getTokenAt(initialRow, initialColumn);
12489
+ this.$tokenIndex = token ? token.index : -1;
12490
+ };
12491
+
12492
+ (function() {
12493
+ this.stepBackward = function() {
12494
+ this.$tokenIndex -= 1;
12495
+
12496
+ while (this.$tokenIndex < 0) {
12497
+ this.$row -= 1;
12498
+ if (this.$row < 0) {
12499
+ this.$row = 0;
12500
+ return null;
12501
+ }
12502
+
12503
+ this.$rowTokens = this.$session.getTokens(this.$row);
12504
+ this.$tokenIndex = this.$rowTokens.length - 1;
12505
+ }
12506
+
12507
+ return this.$rowTokens[this.$tokenIndex];
12508
+ };
12509
+ this.stepForward = function() {
12510
+ this.$tokenIndex += 1;
12511
+ var rowCount;
12512
+ while (this.$tokenIndex >= this.$rowTokens.length) {
12513
+ this.$row += 1;
12514
+ if (!rowCount)
12515
+ rowCount = this.$session.getLength();
12516
+ if (this.$row >= rowCount) {
12517
+ this.$row = rowCount - 1;
12518
+ return null;
12519
+ }
12520
+
12521
+ this.$rowTokens = this.$session.getTokens(this.$row);
12522
+ this.$tokenIndex = 0;
12523
+ }
12524
+
12525
+ return this.$rowTokens[this.$tokenIndex];
12526
+ };
12527
+ this.getCurrentToken = function () {
12528
+ return this.$rowTokens[this.$tokenIndex];
12529
+ };
12530
+ this.getCurrentTokenRow = function () {
12531
+ return this.$row;
12532
+ };
12533
+ this.getCurrentTokenColumn = function() {
12534
+ var rowTokens = this.$rowTokens;
12535
+ var tokenIndex = this.$tokenIndex;
12536
+ var column = rowTokens[tokenIndex].start;
12537
+ if (column !== undefined)
12538
+ return column;
12539
+
12540
+ column = 0;
12541
+ while (tokenIndex > 0) {
12542
+ tokenIndex -= 1;
12543
+ column += rowTokens[tokenIndex].value.length;
12544
+ }
12545
+
12546
+ return column;
12547
+ };
12548
+
12549
+ }).call(TokenIterator.prototype);
12550
+
12551
+ exports.TokenIterator = TokenIterator;
12552
+ });
12553
+
12554
+ ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(acequire, exports, module) {
12555
+ "use strict";
12556
+
12557
+ var Tokenizer = acequire("../tokenizer").Tokenizer;
12558
+ var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules;
12559
+ var Behaviour = acequire("./behaviour").Behaviour;
12560
+ var unicode = acequire("../unicode");
12561
+ var lang = acequire("../lib/lang");
12562
+ var TokenIterator = acequire("../token_iterator").TokenIterator;
12563
+ var Range = acequire("../range").Range;
12564
+
12565
+ var Mode = function() {
12566
+ this.HighlightRules = TextHighlightRules;
12567
+ this.$behaviour = new Behaviour();
12568
+ };
12569
+
12570
+ (function() {
12571
+
12572
+ this.tokenRe = new RegExp("^["
12573
+ + unicode.packages.L
12574
+ + unicode.packages.Mn + unicode.packages.Mc
12575
+ + unicode.packages.Nd
12576
+ + unicode.packages.Pc + "\\$_]+", "g"
12577
+ );
12578
+
12579
+ this.nonTokenRe = new RegExp("^(?:[^"
12580
+ + unicode.packages.L
12581
+ + unicode.packages.Mn + unicode.packages.Mc
12582
+ + unicode.packages.Nd
12583
+ + unicode.packages.Pc + "\\$_]|\\s])+", "g"
12584
+ );
12585
+
12586
+ this.getTokenizer = function() {
12587
+ if (!this.$tokenizer) {
12588
+ this.$highlightRules = this.$highlightRules || new this.HighlightRules();
12589
+ this.$tokenizer = new Tokenizer(this.$highlightRules.getRules());
12590
+ }
12591
+ return this.$tokenizer;
12592
+ };
12593
+
12594
+ this.lineCommentStart = "";
12595
+ this.blockComment = "";
12596
+
12597
+ this.toggleCommentLines = function(state, session, startRow, endRow) {
12598
+ var doc = session.doc;
12599
+
12600
+ var ignoreBlankLines = true;
12601
+ var shouldRemove = true;
12602
+ var minIndent = Infinity;
12603
+ var tabSize = session.getTabSize();
12604
+ var insertAtTabStop = false;
12605
+
12606
+ if (!this.lineCommentStart) {
12607
+ if (!this.blockComment)
12608
+ return false;
12609
+ var lineCommentStart = this.blockComment.start;
12610
+ var lineCommentEnd = this.blockComment.end;
12611
+ var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")");
12612
+ var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$");
12613
+
12614
+ var comment = function(line, i) {
12615
+ if (testRemove(line, i))
12616
+ return;
12617
+ if (!ignoreBlankLines || /\S/.test(line)) {
12618
+ doc.insertInLine({row: i, column: line.length}, lineCommentEnd);
12619
+ doc.insertInLine({row: i, column: minIndent}, lineCommentStart);
12620
+ }
12621
+ };
12622
+
12623
+ var uncomment = function(line, i) {
12624
+ var m;
12625
+ if (m = line.match(regexpEnd))
12626
+ doc.removeInLine(i, line.length - m[0].length, line.length);
12627
+ if (m = line.match(regexpStart))
12628
+ doc.removeInLine(i, m[1].length, m[0].length);
12629
+ };
12630
+
12631
+ var testRemove = function(line, row) {
12632
+ if (regexpStart.test(line))
12633
+ return true;
12634
+ var tokens = session.getTokens(row);
12635
+ for (var i = 0; i < tokens.length; i++) {
12636
+ if (tokens[i].type === 'comment')
12637
+ return true;
12638
+ }
12639
+ };
12640
+ } else {
12641
+ if (Array.isArray(this.lineCommentStart)) {
12642
+ var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|");
12643
+ var lineCommentStart = this.lineCommentStart[0];
12644
+ } else {
12645
+ var regexpStart = lang.escapeRegExp(this.lineCommentStart);
12646
+ var lineCommentStart = this.lineCommentStart;
12647
+ }
12648
+ regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?");
12649
+
12650
+ insertAtTabStop = session.getUseSoftTabs();
12651
+
12652
+ var uncomment = function(line, i) {
12653
+ var m = line.match(regexpStart);
12654
+ if (!m) return;
12655
+ var start = m[1].length, end = m[0].length;
12656
+ if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ")
12657
+ end--;
12658
+ doc.removeInLine(i, start, end);
12659
+ };
12660
+ var commentWithSpace = lineCommentStart + " ";
12661
+ var comment = function(line, i) {
12662
+ if (!ignoreBlankLines || /\S/.test(line)) {
12663
+ if (shouldInsertSpace(line, minIndent, minIndent))
12664
+ doc.insertInLine({row: i, column: minIndent}, commentWithSpace);
12665
+ else
12666
+ doc.insertInLine({row: i, column: minIndent}, lineCommentStart);
12667
+ }
12668
+ };
12669
+ var testRemove = function(line, i) {
12670
+ return regexpStart.test(line);
12671
+ };
12672
+
12673
+ var shouldInsertSpace = function(line, before, after) {
12674
+ var spaces = 0;
12675
+ while (before-- && line.charAt(before) == " ")
12676
+ spaces++;
12677
+ if (spaces % tabSize != 0)
12678
+ return false;
12679
+ var spaces = 0;
12680
+ while (line.charAt(after++) == " ")
12681
+ spaces++;
12682
+ if (tabSize > 2)
12683
+ return spaces % tabSize != tabSize - 1;
12684
+ else
12685
+ return spaces % tabSize == 0;
12686
+ return true;
12687
+ };
12688
+ }
12689
+
12690
+ function iter(fun) {
12691
+ for (var i = startRow; i <= endRow; i++)
12692
+ fun(doc.getLine(i), i);
12693
+ }
12694
+
12695
+
12696
+ var minEmptyLength = Infinity;
12697
+ iter(function(line, i) {
12698
+ var indent = line.search(/\S/);
12699
+ if (indent !== -1) {
12700
+ if (indent < minIndent)
12701
+ minIndent = indent;
12702
+ if (shouldRemove && !testRemove(line, i))
12703
+ shouldRemove = false;
12704
+ } else if (minEmptyLength > line.length) {
12705
+ minEmptyLength = line.length;
12706
+ }
12707
+ });
12708
+
12709
+ if (minIndent == Infinity) {
12710
+ minIndent = minEmptyLength;
12711
+ ignoreBlankLines = false;
12712
+ shouldRemove = false;
12713
+ }
12714
+
12715
+ if (insertAtTabStop && minIndent % tabSize != 0)
12716
+ minIndent = Math.floor(minIndent / tabSize) * tabSize;
12717
+
12718
+ iter(shouldRemove ? uncomment : comment);
12719
+ };
12720
+
12721
+ this.toggleBlockComment = function(state, session, range, cursor) {
12722
+ var comment = this.blockComment;
12723
+ if (!comment)
12724
+ return;
12725
+ if (!comment.start && comment[0])
12726
+ comment = comment[0];
12727
+
12728
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
12729
+ var token = iterator.getCurrentToken();
12730
+
12731
+ var sel = session.selection;
12732
+ var initialRange = session.selection.toOrientedRange();
12733
+ var startRow, colDiff;
12734
+
12735
+ if (token && /comment/.test(token.type)) {
12736
+ var startRange, endRange;
12737
+ while (token && /comment/.test(token.type)) {
12738
+ var i = token.value.indexOf(comment.start);
12739
+ if (i != -1) {
12740
+ var row = iterator.getCurrentTokenRow();
12741
+ var column = iterator.getCurrentTokenColumn() + i;
12742
+ startRange = new Range(row, column, row, column + comment.start.length);
12743
+ break;
12744
+ }
12745
+ token = iterator.stepBackward();
12746
+ }
12747
+
12748
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
12749
+ var token = iterator.getCurrentToken();
12750
+ while (token && /comment/.test(token.type)) {
12751
+ var i = token.value.indexOf(comment.end);
12752
+ if (i != -1) {
12753
+ var row = iterator.getCurrentTokenRow();
12754
+ var column = iterator.getCurrentTokenColumn() + i;
12755
+ endRange = new Range(row, column, row, column + comment.end.length);
12756
+ break;
12757
+ }
12758
+ token = iterator.stepForward();
12759
+ }
12760
+ if (endRange)
12761
+ session.remove(endRange);
12762
+ if (startRange) {
12763
+ session.remove(startRange);
12764
+ startRow = startRange.start.row;
12765
+ colDiff = -comment.start.length;
12766
+ }
12767
+ } else {
12768
+ colDiff = comment.start.length;
12769
+ startRow = range.start.row;
12770
+ session.insert(range.end, comment.end);
12771
+ session.insert(range.start, comment.start);
12772
+ }
12773
+ if (initialRange.start.row == startRow)
12774
+ initialRange.start.column += colDiff;
12775
+ if (initialRange.end.row == startRow)
12776
+ initialRange.end.column += colDiff;
12777
+ session.selection.fromOrientedRange(initialRange);
12778
+ };
12779
+
12780
+ this.getNextLineIndent = function(state, line, tab) {
12781
+ return this.$getIndent(line);
12782
+ };
12783
+
12784
+ this.checkOutdent = function(state, line, input) {
12785
+ return false;
12786
+ };
12787
+
12788
+ this.autoOutdent = function(state, doc, row) {
12789
+ };
12790
+
12791
+ this.$getIndent = function(line) {
12792
+ return line.match(/^\s*/)[0];
12793
+ };
12794
+
12795
+ this.createWorker = function(session) {
12796
+ return null;
12797
+ };
12798
+
12799
+ this.createModeDelegates = function (mapping) {
12800
+ this.$embeds = [];
12801
+ this.$modes = {};
12802
+ for (var i in mapping) {
12803
+ if (mapping[i]) {
12804
+ this.$embeds.push(i);
12805
+ this.$modes[i] = new mapping[i]();
12806
+ }
12807
+ }
12808
+
12809
+ var delegations = ['toggleBlockComment', 'toggleCommentLines', 'getNextLineIndent',
12810
+ 'checkOutdent', 'autoOutdent', 'transformAction', 'getCompletions'];
12811
+
12812
+ for (var i = 0; i < delegations.length; i++) {
12813
+ (function(scope) {
12814
+ var functionName = delegations[i];
12815
+ var defaultHandler = scope[functionName];
12816
+ scope[delegations[i]] = function() {
12817
+ return this.$delegator(functionName, arguments, defaultHandler);
12818
+ };
12819
+ } (this));
12820
+ }
12821
+ };
12822
+
12823
+ this.$delegator = function(method, args, defaultHandler) {
12824
+ var state = args[0];
12825
+ if (typeof state != "string")
12826
+ state = state[0];
12827
+ for (var i = 0; i < this.$embeds.length; i++) {
12828
+ if (!this.$modes[this.$embeds[i]]) continue;
12829
+
12830
+ var split = state.split(this.$embeds[i]);
12831
+ if (!split[0] && split[1]) {
12832
+ args[0] = split[1];
12833
+ var mode = this.$modes[this.$embeds[i]];
12834
+ return mode[method].apply(mode, args);
12835
+ }
12836
+ }
12837
+ var ret = defaultHandler.apply(this, args);
12838
+ return defaultHandler ? ret : undefined;
12839
+ };
12840
+
12841
+ this.transformAction = function(state, action, editor, session, param) {
12842
+ if (this.$behaviour) {
12843
+ var behaviours = this.$behaviour.getBehaviours();
12844
+ for (var key in behaviours) {
12845
+ if (behaviours[key][action]) {
12846
+ var ret = behaviours[key][action].apply(this, arguments);
12847
+ if (ret) {
12848
+ return ret;
12849
+ }
12850
+ }
12851
+ }
12852
+ }
12853
+ };
12854
+
12855
+ this.getKeywords = function(append) {
12856
+ if (!this.completionKeywords) {
12857
+ var rules = this.$tokenizer.rules;
12858
+ var completionKeywords = [];
12859
+ for (var rule in rules) {
12860
+ var ruleItr = rules[rule];
12861
+ for (var r = 0, l = ruleItr.length; r < l; r++) {
12862
+ if (typeof ruleItr[r].token === "string") {
12863
+ if (/keyword|support|storage/.test(ruleItr[r].token))
12864
+ completionKeywords.push(ruleItr[r].regex);
12865
+ }
12866
+ else if (typeof ruleItr[r].token === "object") {
12867
+ for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) {
12868
+ if (/keyword|support|storage/.test(ruleItr[r].token[a])) {
12869
+ var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a];
12870
+ completionKeywords.push(rule.substr(1, rule.length - 2));
12871
+ }
12872
+ }
12873
+ }
12874
+ }
12875
+ }
12876
+ this.completionKeywords = completionKeywords;
12877
+ }
12878
+ if (!append)
12879
+ return this.$keywordList;
12880
+ return completionKeywords.concat(this.$keywordList || []);
12881
+ };
12882
+
12883
+ this.$createKeywordList = function() {
12884
+ if (!this.$highlightRules)
12885
+ this.getTokenizer();
12886
+ return this.$keywordList = this.$highlightRules.$keywordList || [];
12887
+ };
12888
+
12889
+ this.getCompletions = function(state, session, pos, prefix) {
12890
+ var keywords = this.$keywordList || this.$createKeywordList();
12891
+ return keywords.map(function(word) {
12892
+ return {
12893
+ name: word,
12894
+ value: word,
12895
+ score: 0,
12896
+ meta: "keyword"
12897
+ };
12898
+ });
12899
+ };
12900
+
12901
+ this.$id = "ace/mode/text";
12902
+ }).call(Mode.prototype);
12903
+
12904
+ exports.Mode = Mode;
12905
+ });
12906
+
12907
+ ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) {
12908
+ "use strict";
12909
+
12910
+ var oop = acequire("./lib/oop");
12911
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
12912
+
12913
+ var Anchor = exports.Anchor = function(doc, row, column) {
12914
+ this.$onChange = this.onChange.bind(this);
12915
+ this.attach(doc);
12916
+
12917
+ if (typeof column == "undefined")
12918
+ this.setPosition(row.row, row.column);
12919
+ else
12920
+ this.setPosition(row, column);
12921
+ };
12922
+
12923
+ (function() {
12924
+
12925
+ oop.implement(this, EventEmitter);
12926
+ this.getPosition = function() {
12927
+ return this.$clipPositionToDocument(this.row, this.column);
12928
+ };
12929
+ this.getDocument = function() {
12930
+ return this.document;
12931
+ };
12932
+ this.$insertRight = false;
12933
+ this.onChange = function(e) {
12934
+ var delta = e.data;
12935
+ var range = delta.range;
12936
+
12937
+ if (range.start.row == range.end.row && range.start.row != this.row)
12938
+ return;
12939
+
12940
+ if (range.start.row > this.row)
12941
+ return;
12942
+
12943
+ if (range.start.row == this.row && range.start.column > this.column)
12944
+ return;
12945
+
12946
+ var row = this.row;
12947
+ var column = this.column;
12948
+ var start = range.start;
12949
+ var end = range.end;
12950
+
12951
+ if (delta.action === "insertText") {
12952
+ if (start.row === row && start.column <= column) {
12953
+ if (start.column === column && this.$insertRight) {
12954
+ } else if (start.row === end.row) {
12955
+ column += end.column - start.column;
12956
+ } else {
12957
+ column -= start.column;
12958
+ row += end.row - start.row;
12959
+ }
12960
+ } else if (start.row !== end.row && start.row < row) {
12961
+ row += end.row - start.row;
12962
+ }
12963
+ } else if (delta.action === "insertLines") {
12964
+ if (start.row === row && column === 0 && this.$insertRight) {
12965
+ }
12966
+ else if (start.row <= row) {
12967
+ row += end.row - start.row;
12968
+ }
12969
+ } else if (delta.action === "removeText") {
12970
+ if (start.row === row && start.column < column) {
12971
+ if (end.column >= column)
12972
+ column = start.column;
12973
+ else
12974
+ column = Math.max(0, column - (end.column - start.column));
12975
+
12976
+ } else if (start.row !== end.row && start.row < row) {
12977
+ if (end.row === row)
12978
+ column = Math.max(0, column - end.column) + start.column;
12979
+ row -= (end.row - start.row);
12980
+ } else if (end.row === row) {
12981
+ row -= end.row - start.row;
12982
+ column = Math.max(0, column - end.column) + start.column;
12983
+ }
12984
+ } else if (delta.action == "removeLines") {
12985
+ if (start.row <= row) {
12986
+ if (end.row <= row)
12987
+ row -= end.row - start.row;
12988
+ else {
12989
+ row = start.row;
12990
+ column = 0;
12991
+ }
12992
+ }
12993
+ }
12994
+
12995
+ this.setPosition(row, column, true);
12996
+ };
12997
+ this.setPosition = function(row, column, noClip) {
12998
+ var pos;
12999
+ if (noClip) {
13000
+ pos = {
13001
+ row: row,
13002
+ column: column
13003
+ };
13004
+ } else {
13005
+ pos = this.$clipPositionToDocument(row, column);
13006
+ }
13007
+
13008
+ if (this.row == pos.row && this.column == pos.column)
13009
+ return;
13010
+
13011
+ var old = {
13012
+ row: this.row,
13013
+ column: this.column
13014
+ };
13015
+
13016
+ this.row = pos.row;
13017
+ this.column = pos.column;
13018
+ this._signal("change", {
13019
+ old: old,
13020
+ value: pos
13021
+ });
13022
+ };
13023
+ this.detach = function() {
13024
+ this.document.removeEventListener("change", this.$onChange);
13025
+ };
13026
+ this.attach = function(doc) {
13027
+ this.document = doc || this.document;
13028
+ this.document.on("change", this.$onChange);
13029
+ };
13030
+ this.$clipPositionToDocument = function(row, column) {
13031
+ var pos = {};
13032
+
13033
+ if (row >= this.document.getLength()) {
13034
+ pos.row = Math.max(0, this.document.getLength() - 1);
13035
+ pos.column = this.document.getLine(pos.row).length;
13036
+ }
13037
+ else if (row < 0) {
13038
+ pos.row = 0;
13039
+ pos.column = 0;
13040
+ }
13041
+ else {
13042
+ pos.row = row;
13043
+ pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
13044
+ }
13045
+
13046
+ if (column < 0)
13047
+ pos.column = 0;
13048
+
13049
+ return pos;
13050
+ };
13051
+
13052
+ }).call(Anchor.prototype);
13053
+
13054
+ });
13055
+
13056
+ ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(acequire, exports, module) {
13057
+ "use strict";
13058
+
13059
+ var oop = acequire("./lib/oop");
13060
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
13061
+ var Range = acequire("./range").Range;
13062
+ var Anchor = acequire("./anchor").Anchor;
13063
+
13064
+ var Document = function(text) {
13065
+ this.$lines = [];
13066
+ if (text.length === 0) {
13067
+ this.$lines = [""];
13068
+ } else if (Array.isArray(text)) {
13069
+ this._insertLines(0, text);
13070
+ } else {
13071
+ this.insert({row: 0, column:0}, text);
13072
+ }
13073
+ };
13074
+
13075
+ (function() {
13076
+
13077
+ oop.implement(this, EventEmitter);
13078
+ this.setValue = function(text) {
13079
+ var len = this.getLength();
13080
+ this.remove(new Range(0, 0, len, this.getLine(len-1).length));
13081
+ this.insert({row: 0, column:0}, text);
13082
+ };
13083
+ this.getValue = function() {
13084
+ return this.getAllLines().join(this.getNewLineCharacter());
13085
+ };
13086
+ this.createAnchor = function(row, column) {
13087
+ return new Anchor(this, row, column);
13088
+ };
13089
+ if ("aaa".split(/a/).length === 0)
13090
+ this.$split = function(text) {
13091
+ return text.replace(/\r\n|\r/g, "\n").split("\n");
13092
+ };
13093
+ else
13094
+ this.$split = function(text) {
13095
+ return text.split(/\r\n|\r|\n/);
13096
+ };
13097
+
13098
+
13099
+ this.$detectNewLine = function(text) {
13100
+ var match = text.match(/^.*?(\r\n|\r|\n)/m);
13101
+ this.$autoNewLine = match ? match[1] : "\n";
13102
+ this._signal("changeNewLineMode");
13103
+ };
13104
+ this.getNewLineCharacter = function() {
13105
+ switch (this.$newLineMode) {
13106
+ case "windows":
13107
+ return "\r\n";
13108
+ case "unix":
13109
+ return "\n";
13110
+ default:
13111
+ return this.$autoNewLine || "\n";
13112
+ }
13113
+ };
13114
+
13115
+ this.$autoNewLine = "";
13116
+ this.$newLineMode = "auto";
13117
+ this.setNewLineMode = function(newLineMode) {
13118
+ if (this.$newLineMode === newLineMode)
13119
+ return;
13120
+
13121
+ this.$newLineMode = newLineMode;
13122
+ this._signal("changeNewLineMode");
13123
+ };
13124
+ this.getNewLineMode = function() {
13125
+ return this.$newLineMode;
13126
+ };
13127
+ this.isNewLine = function(text) {
13128
+ return (text == "\r\n" || text == "\r" || text == "\n");
13129
+ };
13130
+ this.getLine = function(row) {
13131
+ return this.$lines[row] || "";
13132
+ };
13133
+ this.getLines = function(firstRow, lastRow) {
13134
+ return this.$lines.slice(firstRow, lastRow + 1);
13135
+ };
13136
+ this.getAllLines = function() {
13137
+ return this.getLines(0, this.getLength());
13138
+ };
13139
+ this.getLength = function() {
13140
+ return this.$lines.length;
13141
+ };
13142
+ this.getTextRange = function(range) {
13143
+ if (range.start.row == range.end.row) {
13144
+ return this.getLine(range.start.row)
13145
+ .substring(range.start.column, range.end.column);
13146
+ }
13147
+ var lines = this.getLines(range.start.row, range.end.row);
13148
+ lines[0] = (lines[0] || "").substring(range.start.column);
13149
+ var l = lines.length - 1;
13150
+ if (range.end.row - range.start.row == l)
13151
+ lines[l] = lines[l].substring(0, range.end.column);
13152
+ return lines.join(this.getNewLineCharacter());
13153
+ };
13154
+
13155
+ this.$clipPosition = function(position) {
13156
+ var length = this.getLength();
13157
+ if (position.row >= length) {
13158
+ position.row = Math.max(0, length - 1);
13159
+ position.column = this.getLine(length-1).length;
13160
+ } else if (position.row < 0)
13161
+ position.row = 0;
13162
+ return position;
13163
+ };
13164
+ this.insert = function(position, text) {
13165
+ if (!text || text.length === 0)
13166
+ return position;
13167
+
13168
+ position = this.$clipPosition(position);
13169
+ if (this.getLength() <= 1)
13170
+ this.$detectNewLine(text);
13171
+
13172
+ var lines = this.$split(text);
13173
+ var firstLine = lines.splice(0, 1)[0];
13174
+ var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
13175
+
13176
+ position = this.insertInLine(position, firstLine);
13177
+ if (lastLine !== null) {
13178
+ position = this.insertNewLine(position); // terminate first line
13179
+ position = this._insertLines(position.row, lines);
13180
+ position = this.insertInLine(position, lastLine || "");
13181
+ }
13182
+ return position;
13183
+ };
13184
+ this.insertLines = function(row, lines) {
13185
+ if (row >= this.getLength())
13186
+ return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
13187
+ return this._insertLines(Math.max(row, 0), lines);
13188
+ };
13189
+ this._insertLines = function(row, lines) {
13190
+ if (lines.length == 0)
13191
+ return {row: row, column: 0};
13192
+ while (lines.length > 0xF000) {
13193
+ var end = this._insertLines(row, lines.slice(0, 0xF000));
13194
+ lines = lines.slice(0xF000);
13195
+ row = end.row;
13196
+ }
13197
+
13198
+ var args = [row, 0];
13199
+ args.push.apply(args, lines);
13200
+ this.$lines.splice.apply(this.$lines, args);
13201
+
13202
+ var range = new Range(row, 0, row + lines.length, 0);
13203
+ var delta = {
13204
+ action: "insertLines",
13205
+ range: range,
13206
+ lines: lines
13207
+ };
13208
+ this._signal("change", { data: delta });
13209
+ return range.end;
13210
+ };
13211
+ this.insertNewLine = function(position) {
13212
+ position = this.$clipPosition(position);
13213
+ var line = this.$lines[position.row] || "";
13214
+
13215
+ this.$lines[position.row] = line.substring(0, position.column);
13216
+ this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
13217
+
13218
+ var end = {
13219
+ row : position.row + 1,
13220
+ column : 0
13221
+ };
13222
+
13223
+ var delta = {
13224
+ action: "insertText",
13225
+ range: Range.fromPoints(position, end),
13226
+ text: this.getNewLineCharacter()
13227
+ };
13228
+ this._signal("change", { data: delta });
13229
+
13230
+ return end;
13231
+ };
13232
+ this.insertInLine = function(position, text) {
13233
+ if (text.length == 0)
13234
+ return position;
13235
+
13236
+ var line = this.$lines[position.row] || "";
13237
+
13238
+ this.$lines[position.row] = line.substring(0, position.column) + text
13239
+ + line.substring(position.column);
13240
+
13241
+ var end = {
13242
+ row : position.row,
13243
+ column : position.column + text.length
13244
+ };
13245
+
13246
+ var delta = {
13247
+ action: "insertText",
13248
+ range: Range.fromPoints(position, end),
13249
+ text: text
13250
+ };
13251
+ this._signal("change", { data: delta });
13252
+
13253
+ return end;
13254
+ };
13255
+ this.remove = function(range) {
13256
+ if (!(range instanceof Range))
13257
+ range = Range.fromPoints(range.start, range.end);
13258
+ range.start = this.$clipPosition(range.start);
13259
+ range.end = this.$clipPosition(range.end);
13260
+
13261
+ if (range.isEmpty())
13262
+ return range.start;
13263
+
13264
+ var firstRow = range.start.row;
13265
+ var lastRow = range.end.row;
13266
+
13267
+ if (range.isMultiLine()) {
13268
+ var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
13269
+ var lastFullRow = lastRow - 1;
13270
+
13271
+ if (range.end.column > 0)
13272
+ this.removeInLine(lastRow, 0, range.end.column);
13273
+
13274
+ if (lastFullRow >= firstFullRow)
13275
+ this._removeLines(firstFullRow, lastFullRow);
13276
+
13277
+ if (firstFullRow != firstRow) {
13278
+ this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
13279
+ this.removeNewLine(range.start.row);
13280
+ }
13281
+ }
13282
+ else {
13283
+ this.removeInLine(firstRow, range.start.column, range.end.column);
13284
+ }
13285
+ return range.start;
13286
+ };
13287
+ this.removeInLine = function(row, startColumn, endColumn) {
13288
+ if (startColumn == endColumn)
13289
+ return;
13290
+
13291
+ var range = new Range(row, startColumn, row, endColumn);
13292
+ var line = this.getLine(row);
13293
+ var removed = line.substring(startColumn, endColumn);
13294
+ var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
13295
+ this.$lines.splice(row, 1, newLine);
13296
+
13297
+ var delta = {
13298
+ action: "removeText",
13299
+ range: range,
13300
+ text: removed
13301
+ };
13302
+ this._signal("change", { data: delta });
13303
+ return range.start;
13304
+ };
13305
+ this.removeLines = function(firstRow, lastRow) {
13306
+ if (firstRow < 0 || lastRow >= this.getLength())
13307
+ return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
13308
+ return this._removeLines(firstRow, lastRow);
13309
+ };
13310
+
13311
+ this._removeLines = function(firstRow, lastRow) {
13312
+ var range = new Range(firstRow, 0, lastRow + 1, 0);
13313
+ var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
13314
+
13315
+ var delta = {
13316
+ action: "removeLines",
13317
+ range: range,
13318
+ nl: this.getNewLineCharacter(),
13319
+ lines: removed
13320
+ };
13321
+ this._signal("change", { data: delta });
13322
+ return removed;
13323
+ };
13324
+ this.removeNewLine = function(row) {
13325
+ var firstLine = this.getLine(row);
13326
+ var secondLine = this.getLine(row+1);
13327
+
13328
+ var range = new Range(row, firstLine.length, row+1, 0);
13329
+ var line = firstLine + secondLine;
13330
+
13331
+ this.$lines.splice(row, 2, line);
13332
+
13333
+ var delta = {
13334
+ action: "removeText",
13335
+ range: range,
13336
+ text: this.getNewLineCharacter()
13337
+ };
13338
+ this._signal("change", { data: delta });
13339
+ };
13340
+ this.replace = function(range, text) {
13341
+ if (!(range instanceof Range))
13342
+ range = Range.fromPoints(range.start, range.end);
13343
+ if (text.length == 0 && range.isEmpty())
13344
+ return range.start;
13345
+ if (text == this.getTextRange(range))
13346
+ return range.end;
13347
+
13348
+ this.remove(range);
13349
+ if (text) {
13350
+ var end = this.insert(range.start, text);
13351
+ }
13352
+ else {
13353
+ end = range.start;
13354
+ }
13355
+
13356
+ return end;
13357
+ };
13358
+ this.applyDeltas = function(deltas) {
13359
+ for (var i=0; i<deltas.length; i++) {
13360
+ var delta = deltas[i];
13361
+ var range = Range.fromPoints(delta.range.start, delta.range.end);
13362
+
13363
+ if (delta.action == "insertLines")
13364
+ this.insertLines(range.start.row, delta.lines);
13365
+ else if (delta.action == "insertText")
13366
+ this.insert(range.start, delta.text);
13367
+ else if (delta.action == "removeLines")
13368
+ this._removeLines(range.start.row, range.end.row - 1);
13369
+ else if (delta.action == "removeText")
13370
+ this.remove(range);
13371
+ }
13372
+ };
13373
+ this.revertDeltas = function(deltas) {
13374
+ for (var i=deltas.length-1; i>=0; i--) {
13375
+ var delta = deltas[i];
13376
+
13377
+ var range = Range.fromPoints(delta.range.start, delta.range.end);
13378
+
13379
+ if (delta.action == "insertLines")
13380
+ this._removeLines(range.start.row, range.end.row - 1);
13381
+ else if (delta.action == "insertText")
13382
+ this.remove(range);
13383
+ else if (delta.action == "removeLines")
13384
+ this._insertLines(range.start.row, delta.lines);
13385
+ else if (delta.action == "removeText")
13386
+ this.insert(range.start, delta.text);
13387
+ }
13388
+ };
13389
+ this.indexToPosition = function(index, startRow) {
13390
+ var lines = this.$lines || this.getAllLines();
13391
+ var newlineLength = this.getNewLineCharacter().length;
13392
+ for (var i = startRow || 0, l = lines.length; i < l; i++) {
13393
+ index -= lines[i].length + newlineLength;
13394
+ if (index < 0)
13395
+ return {row: i, column: index + lines[i].length + newlineLength};
13396
+ }
13397
+ return {row: l-1, column: lines[l-1].length};
13398
+ };
13399
+ this.positionToIndex = function(pos, startRow) {
13400
+ var lines = this.$lines || this.getAllLines();
13401
+ var newlineLength = this.getNewLineCharacter().length;
13402
+ var index = 0;
13403
+ var row = Math.min(pos.row, lines.length);
13404
+ for (var i = startRow || 0; i < row; ++i)
13405
+ index += lines[i].length + newlineLength;
13406
+
13407
+ return index + pos.column;
13408
+ };
13409
+
13410
+ }).call(Document.prototype);
13411
+
13412
+ exports.Document = Document;
13413
+ });
13414
+
13415
+ ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) {
13416
+ "use strict";
13417
+
13418
+ var oop = acequire("./lib/oop");
13419
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
13420
+
13421
+ var BackgroundTokenizer = function(tokenizer, editor) {
13422
+ this.running = false;
13423
+ this.lines = [];
13424
+ this.states = [];
13425
+ this.currentLine = 0;
13426
+ this.tokenizer = tokenizer;
13427
+
13428
+ var self = this;
13429
+
13430
+ this.$worker = function() {
13431
+ if (!self.running) { return; }
13432
+
13433
+ var workerStart = new Date();
13434
+ var currentLine = self.currentLine;
13435
+ var endLine = -1;
13436
+ var doc = self.doc;
13437
+
13438
+ while (self.lines[currentLine])
13439
+ currentLine++;
13440
+
13441
+ var startLine = currentLine;
13442
+
13443
+ var len = doc.getLength();
13444
+ var processedLines = 0;
13445
+ self.running = false;
13446
+ while (currentLine < len) {
13447
+ self.$tokenizeRow(currentLine);
13448
+ endLine = currentLine;
13449
+ do {
13450
+ currentLine++;
13451
+ } while (self.lines[currentLine]);
13452
+ processedLines ++;
13453
+ if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) {
13454
+ self.running = setTimeout(self.$worker, 20);
13455
+ break;
13456
+ }
13457
+ }
13458
+ self.currentLine = currentLine;
13459
+
13460
+ if (startLine <= endLine)
13461
+ self.fireUpdateEvent(startLine, endLine);
13462
+ };
13463
+ };
13464
+
13465
+ (function(){
13466
+
13467
+ oop.implement(this, EventEmitter);
13468
+ this.setTokenizer = function(tokenizer) {
13469
+ this.tokenizer = tokenizer;
13470
+ this.lines = [];
13471
+ this.states = [];
13472
+
13473
+ this.start(0);
13474
+ };
13475
+ this.setDocument = function(doc) {
13476
+ this.doc = doc;
13477
+ this.lines = [];
13478
+ this.states = [];
13479
+
13480
+ this.stop();
13481
+ };
13482
+ this.fireUpdateEvent = function(firstRow, lastRow) {
13483
+ var data = {
13484
+ first: firstRow,
13485
+ last: lastRow
13486
+ };
13487
+ this._signal("update", {data: data});
13488
+ };
13489
+ this.start = function(startRow) {
13490
+ this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength());
13491
+ this.lines.splice(this.currentLine, this.lines.length);
13492
+ this.states.splice(this.currentLine, this.states.length);
13493
+
13494
+ this.stop();
13495
+ this.running = setTimeout(this.$worker, 700);
13496
+ };
13497
+
13498
+ this.scheduleStart = function() {
13499
+ if (!this.running)
13500
+ this.running = setTimeout(this.$worker, 700);
13501
+ }
13502
+
13503
+ this.$updateOnChange = function(delta) {
13504
+ var range = delta.range;
13505
+ var startRow = range.start.row;
13506
+ var len = range.end.row - startRow;
13507
+
13508
+ if (len === 0) {
13509
+ this.lines[startRow] = null;
13510
+ } else if (delta.action == "removeText" || delta.action == "removeLines") {
13511
+ this.lines.splice(startRow, len + 1, null);
13512
+ this.states.splice(startRow, len + 1, null);
13513
+ } else {
13514
+ var args = Array(len + 1);
13515
+ args.unshift(startRow, 1);
13516
+ this.lines.splice.apply(this.lines, args);
13517
+ this.states.splice.apply(this.states, args);
13518
+ }
13519
+
13520
+ this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());
13521
+
13522
+ this.stop();
13523
+ };
13524
+ this.stop = function() {
13525
+ if (this.running)
13526
+ clearTimeout(this.running);
13527
+ this.running = false;
13528
+ };
13529
+ this.getTokens = function(row) {
13530
+ return this.lines[row] || this.$tokenizeRow(row);
13531
+ };
13532
+ this.getState = function(row) {
13533
+ if (this.currentLine == row)
13534
+ this.$tokenizeRow(row);
13535
+ return this.states[row] || "start";
13536
+ };
13537
+
13538
+ this.$tokenizeRow = function(row) {
13539
+ var line = this.doc.getLine(row);
13540
+ var state = this.states[row - 1];
13541
+
13542
+ var data = this.tokenizer.getLineTokens(line, state, row);
13543
+
13544
+ if (this.states[row] + "" !== data.state + "") {
13545
+ this.states[row] = data.state;
13546
+ this.lines[row + 1] = null;
13547
+ if (this.currentLine > row + 1)
13548
+ this.currentLine = row + 1;
13549
+ } else if (this.currentLine == row) {
13550
+ this.currentLine = row + 1;
13551
+ }
13552
+
13553
+ return this.lines[row] = data.tokens;
13554
+ };
13555
+
13556
+ }).call(BackgroundTokenizer.prototype);
13557
+
13558
+ exports.BackgroundTokenizer = BackgroundTokenizer;
13559
+ });
13560
+
13561
+ ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) {
13562
+ "use strict";
13563
+
13564
+ var lang = acequire("./lib/lang");
13565
+ var oop = acequire("./lib/oop");
13566
+ var Range = acequire("./range").Range;
13567
+
13568
+ var SearchHighlight = function(regExp, clazz, type) {
13569
+ this.setRegexp(regExp);
13570
+ this.clazz = clazz;
13571
+ this.type = type || "text";
13572
+ };
13573
+
13574
+ (function() {
13575
+ this.MAX_RANGES = 500;
13576
+
13577
+ this.setRegexp = function(regExp) {
13578
+ if (this.regExp+"" == regExp+"")
13579
+ return;
13580
+ this.regExp = regExp;
13581
+ this.cache = [];
13582
+ };
13583
+
13584
+ this.update = function(html, markerLayer, session, config) {
13585
+ if (!this.regExp)
13586
+ return;
13587
+ var start = config.firstRow, end = config.lastRow;
13588
+
13589
+ for (var i = start; i <= end; i++) {
13590
+ var ranges = this.cache[i];
13591
+ if (ranges == null) {
13592
+ ranges = lang.getMatchOffsets(session.getLine(i), this.regExp);
13593
+ if (ranges.length > this.MAX_RANGES)
13594
+ ranges = ranges.slice(0, this.MAX_RANGES);
13595
+ ranges = ranges.map(function(match) {
13596
+ return new Range(i, match.offset, i, match.offset + match.length);
13597
+ });
13598
+ this.cache[i] = ranges.length ? ranges : "";
13599
+ }
13600
+
13601
+ for (var j = ranges.length; j --; ) {
13602
+ markerLayer.drawSingleLineMarker(
13603
+ html, ranges[j].toScreenRange(session), this.clazz, config);
13604
+ }
13605
+ }
13606
+ };
13607
+
13608
+ }).call(SearchHighlight.prototype);
13609
+
13610
+ exports.SearchHighlight = SearchHighlight;
13611
+ });
13612
+
13613
+ ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(acequire, exports, module) {
13614
+ "use strict";
13615
+
13616
+ var Range = acequire("../range").Range;
13617
+ function FoldLine(foldData, folds) {
13618
+ this.foldData = foldData;
13619
+ if (Array.isArray(folds)) {
13620
+ this.folds = folds;
13621
+ } else {
13622
+ folds = this.folds = [ folds ];
13623
+ }
13624
+
13625
+ var last = folds[folds.length - 1];
13626
+ this.range = new Range(folds[0].start.row, folds[0].start.column,
13627
+ last.end.row, last.end.column);
13628
+ this.start = this.range.start;
13629
+ this.end = this.range.end;
13630
+
13631
+ this.folds.forEach(function(fold) {
13632
+ fold.setFoldLine(this);
13633
+ }, this);
13634
+ }
13635
+
13636
+ (function() {
13637
+ this.shiftRow = function(shift) {
13638
+ this.start.row += shift;
13639
+ this.end.row += shift;
13640
+ this.folds.forEach(function(fold) {
13641
+ fold.start.row += shift;
13642
+ fold.end.row += shift;
13643
+ });
13644
+ };
13645
+
13646
+ this.addFold = function(fold) {
13647
+ if (fold.sameRow) {
13648
+ if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
13649
+ throw new Error("Can't add a fold to this FoldLine as it has no connection");
13650
+ }
13651
+ this.folds.push(fold);
13652
+ this.folds.sort(function(a, b) {
13653
+ return -a.range.compareEnd(b.start.row, b.start.column);
13654
+ });
13655
+ if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {
13656
+ this.end.row = fold.end.row;
13657
+ this.end.column = fold.end.column;
13658
+ } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {
13659
+ this.start.row = fold.start.row;
13660
+ this.start.column = fold.start.column;
13661
+ }
13662
+ } else if (fold.start.row == this.end.row) {
13663
+ this.folds.push(fold);
13664
+ this.end.row = fold.end.row;
13665
+ this.end.column = fold.end.column;
13666
+ } else if (fold.end.row == this.start.row) {
13667
+ this.folds.unshift(fold);
13668
+ this.start.row = fold.start.row;
13669
+ this.start.column = fold.start.column;
13670
+ } else {
13671
+ throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");
13672
+ }
13673
+ fold.foldLine = this;
13674
+ };
13675
+
13676
+ this.containsRow = function(row) {
13677
+ return row >= this.start.row && row <= this.end.row;
13678
+ };
13679
+
13680
+ this.walk = function(callback, endRow, endColumn) {
13681
+ var lastEnd = 0,
13682
+ folds = this.folds,
13683
+ fold,
13684
+ cmp, stop, isNewRow = true;
13685
+
13686
+ if (endRow == null) {
13687
+ endRow = this.end.row;
13688
+ endColumn = this.end.column;
13689
+ }
13690
+
13691
+ for (var i = 0; i < folds.length; i++) {
13692
+ fold = folds[i];
13693
+
13694
+ cmp = fold.range.compareStart(endRow, endColumn);
13695
+ if (cmp == -1) {
13696
+ callback(null, endRow, endColumn, lastEnd, isNewRow);
13697
+ return;
13698
+ }
13699
+
13700
+ stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
13701
+ stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
13702
+ if (stop || cmp === 0) {
13703
+ return;
13704
+ }
13705
+ isNewRow = !fold.sameRow;
13706
+ lastEnd = fold.end.column;
13707
+ }
13708
+ callback(null, endRow, endColumn, lastEnd, isNewRow);
13709
+ };
13710
+
13711
+ this.getNextFoldTo = function(row, column) {
13712
+ var fold, cmp;
13713
+ for (var i = 0; i < this.folds.length; i++) {
13714
+ fold = this.folds[i];
13715
+ cmp = fold.range.compareEnd(row, column);
13716
+ if (cmp == -1) {
13717
+ return {
13718
+ fold: fold,
13719
+ kind: "after"
13720
+ };
13721
+ } else if (cmp === 0) {
13722
+ return {
13723
+ fold: fold,
13724
+ kind: "inside"
13725
+ };
13726
+ }
13727
+ }
13728
+ return null;
13729
+ };
13730
+
13731
+ this.addRemoveChars = function(row, column, len) {
13732
+ var ret = this.getNextFoldTo(row, column),
13733
+ fold, folds;
13734
+ if (ret) {
13735
+ fold = ret.fold;
13736
+ if (ret.kind == "inside"
13737
+ && fold.start.column != column
13738
+ && fold.start.row != row)
13739
+ {
13740
+ window.console && window.console.log(row, column, fold);
13741
+ } else if (fold.start.row == row) {
13742
+ folds = this.folds;
13743
+ var i = folds.indexOf(fold);
13744
+ if (i === 0) {
13745
+ this.start.column += len;
13746
+ }
13747
+ for (i; i < folds.length; i++) {
13748
+ fold = folds[i];
13749
+ fold.start.column += len;
13750
+ if (!fold.sameRow) {
13751
+ return;
13752
+ }
13753
+ fold.end.column += len;
13754
+ }
13755
+ this.end.column += len;
13756
+ }
13757
+ }
13758
+ };
13759
+
13760
+ this.split = function(row, column) {
13761
+ var pos = this.getNextFoldTo(row, column);
13762
+
13763
+ if (!pos || pos.kind == "inside")
13764
+ return null;
13765
+
13766
+ var fold = pos.fold;
13767
+ var folds = this.folds;
13768
+ var foldData = this.foldData;
13769
+
13770
+ var i = folds.indexOf(fold);
13771
+ var foldBefore = folds[i - 1];
13772
+ this.end.row = foldBefore.end.row;
13773
+ this.end.column = foldBefore.end.column;
13774
+ folds = folds.splice(i, folds.length - i);
13775
+
13776
+ var newFoldLine = new FoldLine(foldData, folds);
13777
+ foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
13778
+ return newFoldLine;
13779
+ };
13780
+
13781
+ this.merge = function(foldLineNext) {
13782
+ var folds = foldLineNext.folds;
13783
+ for (var i = 0; i < folds.length; i++) {
13784
+ this.addFold(folds[i]);
13785
+ }
13786
+ var foldData = this.foldData;
13787
+ foldData.splice(foldData.indexOf(foldLineNext), 1);
13788
+ };
13789
+
13790
+ this.toString = function() {
13791
+ var ret = [this.range.toString() + ": [" ];
13792
+
13793
+ this.folds.forEach(function(fold) {
13794
+ ret.push(" " + fold.toString());
13795
+ });
13796
+ ret.push("]");
13797
+ return ret.join("\n");
13798
+ };
13799
+
13800
+ this.idxToPosition = function(idx) {
13801
+ var lastFoldEndColumn = 0;
13802
+
13803
+ for (var i = 0; i < this.folds.length; i++) {
13804
+ var fold = this.folds[i];
13805
+
13806
+ idx -= fold.start.column - lastFoldEndColumn;
13807
+ if (idx < 0) {
13808
+ return {
13809
+ row: fold.start.row,
13810
+ column: fold.start.column + idx
13811
+ };
13812
+ }
13813
+
13814
+ idx -= fold.placeholder.length;
13815
+ if (idx < 0) {
13816
+ return fold.start;
13817
+ }
13818
+
13819
+ lastFoldEndColumn = fold.end.column;
13820
+ }
13821
+
13822
+ return {
13823
+ row: this.end.row,
13824
+ column: this.end.column + idx
13825
+ };
13826
+ };
13827
+ }).call(FoldLine.prototype);
13828
+
13829
+ exports.FoldLine = FoldLine;
13830
+ });
13831
+
13832
+ ace.define("ace/range_list",["require","exports","module","ace/range"], function(acequire, exports, module) {
13833
+ "use strict";
13834
+ var Range = acequire("./range").Range;
13835
+ var comparePoints = Range.comparePoints;
13836
+
13837
+ var RangeList = function() {
13838
+ this.ranges = [];
13839
+ };
13840
+
13841
+ (function() {
13842
+ this.comparePoints = comparePoints;
13843
+
13844
+ this.pointIndex = function(pos, excludeEdges, startIndex) {
13845
+ var list = this.ranges;
13846
+
13847
+ for (var i = startIndex || 0; i < list.length; i++) {
13848
+ var range = list[i];
13849
+ var cmpEnd = comparePoints(pos, range.end);
13850
+ if (cmpEnd > 0)
13851
+ continue;
13852
+ var cmpStart = comparePoints(pos, range.start);
13853
+ if (cmpEnd === 0)
13854
+ return excludeEdges && cmpStart !== 0 ? -i-2 : i;
13855
+ if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges))
13856
+ return i;
13857
+
13858
+ return -i-1;
13859
+ }
13860
+ return -i - 1;
13861
+ };
13862
+
13863
+ this.add = function(range) {
13864
+ var excludeEdges = !range.isEmpty();
13865
+ var startIndex = this.pointIndex(range.start, excludeEdges);
13866
+ if (startIndex < 0)
13867
+ startIndex = -startIndex - 1;
13868
+
13869
+ var endIndex = this.pointIndex(range.end, excludeEdges, startIndex);
13870
+
13871
+ if (endIndex < 0)
13872
+ endIndex = -endIndex - 1;
13873
+ else
13874
+ endIndex++;
13875
+ return this.ranges.splice(startIndex, endIndex - startIndex, range);
13876
+ };
13877
+
13878
+ this.addList = function(list) {
13879
+ var removed = [];
13880
+ for (var i = list.length; i--; ) {
13881
+ removed.push.call(removed, this.add(list[i]));
13882
+ }
13883
+ return removed;
13884
+ };
13885
+
13886
+ this.substractPoint = function(pos) {
13887
+ var i = this.pointIndex(pos);
13888
+
13889
+ if (i >= 0)
13890
+ return this.ranges.splice(i, 1);
13891
+ };
13892
+ this.merge = function() {
13893
+ var removed = [];
13894
+ var list = this.ranges;
13895
+
13896
+ list = list.sort(function(a, b) {
13897
+ return comparePoints(a.start, b.start);
13898
+ });
13899
+
13900
+ var next = list[0], range;
13901
+ for (var i = 1; i < list.length; i++) {
13902
+ range = next;
13903
+ next = list[i];
13904
+ var cmp = comparePoints(range.end, next.start);
13905
+ if (cmp < 0)
13906
+ continue;
13907
+
13908
+ if (cmp == 0 && !range.isEmpty() && !next.isEmpty())
13909
+ continue;
13910
+
13911
+ if (comparePoints(range.end, next.end) < 0) {
13912
+ range.end.row = next.end.row;
13913
+ range.end.column = next.end.column;
13914
+ }
13915
+
13916
+ list.splice(i, 1);
13917
+ removed.push(next);
13918
+ next = range;
13919
+ i--;
13920
+ }
13921
+
13922
+ this.ranges = list;
13923
+
13924
+ return removed;
13925
+ };
13926
+
13927
+ this.contains = function(row, column) {
13928
+ return this.pointIndex({row: row, column: column}) >= 0;
13929
+ };
13930
+
13931
+ this.containsPoint = function(pos) {
13932
+ return this.pointIndex(pos) >= 0;
13933
+ };
13934
+
13935
+ this.rangeAtPoint = function(pos) {
13936
+ var i = this.pointIndex(pos);
13937
+ if (i >= 0)
13938
+ return this.ranges[i];
13939
+ };
13940
+
13941
+
13942
+ this.clipRows = function(startRow, endRow) {
13943
+ var list = this.ranges;
13944
+ if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)
13945
+ return [];
13946
+
13947
+ var startIndex = this.pointIndex({row: startRow, column: 0});
13948
+ if (startIndex < 0)
13949
+ startIndex = -startIndex - 1;
13950
+ var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);
13951
+ if (endIndex < 0)
13952
+ endIndex = -endIndex - 1;
13953
+
13954
+ var clipped = [];
13955
+ for (var i = startIndex; i < endIndex; i++) {
13956
+ clipped.push(list[i]);
13957
+ }
13958
+ return clipped;
13959
+ };
13960
+
13961
+ this.removeAll = function() {
13962
+ return this.ranges.splice(0, this.ranges.length);
13963
+ };
13964
+
13965
+ this.attach = function(session) {
13966
+ if (this.session)
13967
+ this.detach();
13968
+
13969
+ this.session = session;
13970
+ this.onChange = this.$onChange.bind(this);
13971
+
13972
+ this.session.on('change', this.onChange);
13973
+ };
13974
+
13975
+ this.detach = function() {
13976
+ if (!this.session)
13977
+ return;
13978
+ this.session.removeListener('change', this.onChange);
13979
+ this.session = null;
13980
+ };
13981
+
13982
+ this.$onChange = function(e) {
13983
+ var changeRange = e.data.range;
13984
+ if (e.data.action[0] == "i"){
13985
+ var start = changeRange.start;
13986
+ var end = changeRange.end;
13987
+ } else {
13988
+ var end = changeRange.start;
13989
+ var start = changeRange.end;
13990
+ }
13991
+ var startRow = start.row;
13992
+ var endRow = end.row;
13993
+ var lineDif = endRow - startRow;
13994
+
13995
+ var colDiff = -start.column + end.column;
13996
+ var ranges = this.ranges;
13997
+
13998
+ for (var i = 0, n = ranges.length; i < n; i++) {
13999
+ var r = ranges[i];
14000
+ if (r.end.row < startRow)
14001
+ continue;
14002
+ if (r.start.row > startRow)
14003
+ break;
14004
+
14005
+ if (r.start.row == startRow && r.start.column >= start.column ) {
14006
+ if (r.start.column == start.column && this.$insertRight) {
14007
+ } else {
14008
+ r.start.column += colDiff;
14009
+ r.start.row += lineDif;
14010
+ }
14011
+ }
14012
+ if (r.end.row == startRow && r.end.column >= start.column) {
14013
+ if (r.end.column == start.column && this.$insertRight) {
14014
+ continue;
14015
+ }
14016
+ if (r.end.column == start.column && colDiff > 0 && i < n - 1) {
14017
+ if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column)
14018
+ r.end.column -= colDiff;
14019
+ }
14020
+ r.end.column += colDiff;
14021
+ r.end.row += lineDif;
14022
+ }
14023
+ }
14024
+
14025
+ if (lineDif != 0 && i < n) {
14026
+ for (; i < n; i++) {
14027
+ var r = ranges[i];
14028
+ r.start.row += lineDif;
14029
+ r.end.row += lineDif;
14030
+ }
14031
+ }
14032
+ };
14033
+
14034
+ }).call(RangeList.prototype);
14035
+
14036
+ exports.RangeList = RangeList;
14037
+ });
14038
+
14039
+ ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(acequire, exports, module) {
14040
+ "use strict";
14041
+
14042
+ var Range = acequire("../range").Range;
14043
+ var RangeList = acequire("../range_list").RangeList;
14044
+ var oop = acequire("../lib/oop")
14045
+ var Fold = exports.Fold = function(range, placeholder) {
14046
+ this.foldLine = null;
14047
+ this.placeholder = placeholder;
14048
+ this.range = range;
14049
+ this.start = range.start;
14050
+ this.end = range.end;
14051
+
14052
+ this.sameRow = range.start.row == range.end.row;
14053
+ this.subFolds = this.ranges = [];
14054
+ };
14055
+
14056
+ oop.inherits(Fold, RangeList);
14057
+
14058
+ (function() {
14059
+
14060
+ this.toString = function() {
14061
+ return '"' + this.placeholder + '" ' + this.range.toString();
14062
+ };
14063
+
14064
+ this.setFoldLine = function(foldLine) {
14065
+ this.foldLine = foldLine;
14066
+ this.subFolds.forEach(function(fold) {
14067
+ fold.setFoldLine(foldLine);
14068
+ });
14069
+ };
14070
+
14071
+ this.clone = function() {
14072
+ var range = this.range.clone();
14073
+ var fold = new Fold(range, this.placeholder);
14074
+ this.subFolds.forEach(function(subFold) {
14075
+ fold.subFolds.push(subFold.clone());
14076
+ });
14077
+ fold.collapseChildren = this.collapseChildren;
14078
+ return fold;
14079
+ };
14080
+
14081
+ this.addSubFold = function(fold) {
14082
+ if (this.range.isEqual(fold))
14083
+ return;
14084
+
14085
+ if (!this.range.containsRange(fold))
14086
+ throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
14087
+ consumeRange(fold, this.start);
14088
+
14089
+ var row = fold.start.row, column = fold.start.column;
14090
+ for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
14091
+ cmp = this.subFolds[i].range.compare(row, column);
14092
+ if (cmp != 1)
14093
+ break;
14094
+ }
14095
+ var afterStart = this.subFolds[i];
14096
+
14097
+ if (cmp == 0)
14098
+ return afterStart.addSubFold(fold);
14099
+ var row = fold.range.end.row, column = fold.range.end.column;
14100
+ for (var j = i, cmp = -1; j < this.subFolds.length; j++) {
14101
+ cmp = this.subFolds[j].range.compare(row, column);
14102
+ if (cmp != 1)
14103
+ break;
14104
+ }
14105
+ var afterEnd = this.subFolds[j];
14106
+
14107
+ if (cmp == 0)
14108
+ throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
14109
+
14110
+ var consumedFolds = this.subFolds.splice(i, j - i, fold);
14111
+ fold.setFoldLine(this.foldLine);
14112
+
14113
+ return fold;
14114
+ };
14115
+
14116
+ this.restoreRange = function(range) {
14117
+ return restoreRange(range, this.start);
14118
+ };
14119
+
14120
+ }).call(Fold.prototype);
14121
+
14122
+ function consumePoint(point, anchor) {
14123
+ point.row -= anchor.row;
14124
+ if (point.row == 0)
14125
+ point.column -= anchor.column;
14126
+ }
14127
+ function consumeRange(range, anchor) {
14128
+ consumePoint(range.start, anchor);
14129
+ consumePoint(range.end, anchor);
14130
+ }
14131
+ function restorePoint(point, anchor) {
14132
+ if (point.row == 0)
14133
+ point.column += anchor.column;
14134
+ point.row += anchor.row;
14135
+ }
14136
+ function restoreRange(range, anchor) {
14137
+ restorePoint(range.start, anchor);
14138
+ restorePoint(range.end, anchor);
14139
+ }
14140
+
14141
+ });
14142
+
14143
+ ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(acequire, exports, module) {
14144
+ "use strict";
14145
+
14146
+ var Range = acequire("../range").Range;
14147
+ var FoldLine = acequire("./fold_line").FoldLine;
14148
+ var Fold = acequire("./fold").Fold;
14149
+ var TokenIterator = acequire("../token_iterator").TokenIterator;
14150
+
14151
+ function Folding() {
14152
+ this.getFoldAt = function(row, column, side) {
14153
+ var foldLine = this.getFoldLine(row);
14154
+ if (!foldLine)
14155
+ return null;
14156
+
14157
+ var folds = foldLine.folds;
14158
+ for (var i = 0; i < folds.length; i++) {
14159
+ var fold = folds[i];
14160
+ if (fold.range.contains(row, column)) {
14161
+ if (side == 1 && fold.range.isEnd(row, column)) {
14162
+ continue;
14163
+ } else if (side == -1 && fold.range.isStart(row, column)) {
14164
+ continue;
14165
+ }
14166
+ return fold;
14167
+ }
14168
+ }
14169
+ };
14170
+ this.getFoldsInRange = function(range) {
14171
+ var start = range.start;
14172
+ var end = range.end;
14173
+ var foldLines = this.$foldData;
14174
+ var foundFolds = [];
14175
+
14176
+ start.column += 1;
14177
+ end.column -= 1;
14178
+
14179
+ for (var i = 0; i < foldLines.length; i++) {
14180
+ var cmp = foldLines[i].range.compareRange(range);
14181
+ if (cmp == 2) {
14182
+ continue;
14183
+ }
14184
+ else if (cmp == -2) {
14185
+ break;
14186
+ }
14187
+
14188
+ var folds = foldLines[i].folds;
14189
+ for (var j = 0; j < folds.length; j++) {
14190
+ var fold = folds[j];
14191
+ cmp = fold.range.compareRange(range);
14192
+ if (cmp == -2) {
14193
+ break;
14194
+ } else if (cmp == 2) {
14195
+ continue;
14196
+ } else
14197
+ if (cmp == 42) {
14198
+ break;
14199
+ }
14200
+ foundFolds.push(fold);
14201
+ }
14202
+ }
14203
+ start.column -= 1;
14204
+ end.column += 1;
14205
+
14206
+ return foundFolds;
14207
+ };
14208
+
14209
+ this.getFoldsInRangeList = function(ranges) {
14210
+ if (Array.isArray(ranges)) {
14211
+ var folds = [];
14212
+ ranges.forEach(function(range) {
14213
+ folds = folds.concat(this.getFoldsInRange(range));
14214
+ }, this);
14215
+ } else {
14216
+ var folds = this.getFoldsInRange(ranges);
14217
+ }
14218
+ return folds;
14219
+ }
14220
+ this.getAllFolds = function() {
14221
+ var folds = [];
14222
+ var foldLines = this.$foldData;
14223
+
14224
+ for (var i = 0; i < foldLines.length; i++)
14225
+ for (var j = 0; j < foldLines[i].folds.length; j++)
14226
+ folds.push(foldLines[i].folds[j]);
14227
+
14228
+ return folds;
14229
+ };
14230
+ this.getFoldStringAt = function(row, column, trim, foldLine) {
14231
+ foldLine = foldLine || this.getFoldLine(row);
14232
+ if (!foldLine)
14233
+ return null;
14234
+
14235
+ var lastFold = {
14236
+ end: { column: 0 }
14237
+ };
14238
+ var str, fold;
14239
+ for (var i = 0; i < foldLine.folds.length; i++) {
14240
+ fold = foldLine.folds[i];
14241
+ var cmp = fold.range.compareEnd(row, column);
14242
+ if (cmp == -1) {
14243
+ str = this
14244
+ .getLine(fold.start.row)
14245
+ .substring(lastFold.end.column, fold.start.column);
14246
+ break;
14247
+ }
14248
+ else if (cmp === 0) {
14249
+ return null;
14250
+ }
14251
+ lastFold = fold;
14252
+ }
14253
+ if (!str)
14254
+ str = this.getLine(fold.start.row).substring(lastFold.end.column);
14255
+
14256
+ if (trim == -1)
14257
+ return str.substring(0, column - lastFold.end.column);
14258
+ else if (trim == 1)
14259
+ return str.substring(column - lastFold.end.column);
14260
+ else
14261
+ return str;
14262
+ };
14263
+
14264
+ this.getFoldLine = function(docRow, startFoldLine) {
14265
+ var foldData = this.$foldData;
14266
+ var i = 0;
14267
+ if (startFoldLine)
14268
+ i = foldData.indexOf(startFoldLine);
14269
+ if (i == -1)
14270
+ i = 0;
14271
+ for (i; i < foldData.length; i++) {
14272
+ var foldLine = foldData[i];
14273
+ if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {
14274
+ return foldLine;
14275
+ } else if (foldLine.end.row > docRow) {
14276
+ return null;
14277
+ }
14278
+ }
14279
+ return null;
14280
+ };
14281
+ this.getNextFoldLine = function(docRow, startFoldLine) {
14282
+ var foldData = this.$foldData;
14283
+ var i = 0;
14284
+ if (startFoldLine)
14285
+ i = foldData.indexOf(startFoldLine);
14286
+ if (i == -1)
14287
+ i = 0;
14288
+ for (i; i < foldData.length; i++) {
14289
+ var foldLine = foldData[i];
14290
+ if (foldLine.end.row >= docRow) {
14291
+ return foldLine;
14292
+ }
14293
+ }
14294
+ return null;
14295
+ };
14296
+
14297
+ this.getFoldedRowCount = function(first, last) {
14298
+ var foldData = this.$foldData, rowCount = last-first+1;
14299
+ for (var i = 0; i < foldData.length; i++) {
14300
+ var foldLine = foldData[i],
14301
+ end = foldLine.end.row,
14302
+ start = foldLine.start.row;
14303
+ if (end >= last) {
14304
+ if(start < last) {
14305
+ if(start >= first)
14306
+ rowCount -= last-start;
14307
+ else
14308
+ rowCount = 0;//in one fold
14309
+ }
14310
+ break;
14311
+ } else if(end >= first){
14312
+ if (start >= first) //fold inside range
14313
+ rowCount -= end-start;
14314
+ else
14315
+ rowCount -= end-first+1;
14316
+ }
14317
+ }
14318
+ return rowCount;
14319
+ };
14320
+
14321
+ this.$addFoldLine = function(foldLine) {
14322
+ this.$foldData.push(foldLine);
14323
+ this.$foldData.sort(function(a, b) {
14324
+ return a.start.row - b.start.row;
14325
+ });
14326
+ return foldLine;
14327
+ };
14328
+ this.addFold = function(placeholder, range) {
14329
+ var foldData = this.$foldData;
14330
+ var added = false;
14331
+ var fold;
14332
+
14333
+ if (placeholder instanceof Fold)
14334
+ fold = placeholder;
14335
+ else {
14336
+ fold = new Fold(range, placeholder);
14337
+ fold.collapseChildren = range.collapseChildren;
14338
+ }
14339
+ this.$clipRangeToDocument(fold.range);
14340
+
14341
+ var startRow = fold.start.row;
14342
+ var startColumn = fold.start.column;
14343
+ var endRow = fold.end.row;
14344
+ var endColumn = fold.end.column;
14345
+ if (!(startRow < endRow ||
14346
+ startRow == endRow && startColumn <= endColumn - 2))
14347
+ throw new Error("The range has to be at least 2 characters width");
14348
+
14349
+ var startFold = this.getFoldAt(startRow, startColumn, 1);
14350
+ var endFold = this.getFoldAt(endRow, endColumn, -1);
14351
+ if (startFold && endFold == startFold)
14352
+ return startFold.addSubFold(fold);
14353
+
14354
+ if (startFold && !startFold.range.isStart(startRow, startColumn))
14355
+ this.removeFold(startFold);
14356
+
14357
+ if (endFold && !endFold.range.isEnd(endRow, endColumn))
14358
+ this.removeFold(endFold);
14359
+ var folds = this.getFoldsInRange(fold.range);
14360
+ if (folds.length > 0) {
14361
+ this.removeFolds(folds);
14362
+ folds.forEach(function(subFold) {
14363
+ fold.addSubFold(subFold);
14364
+ });
14365
+ }
14366
+
14367
+ for (var i = 0; i < foldData.length; i++) {
14368
+ var foldLine = foldData[i];
14369
+ if (endRow == foldLine.start.row) {
14370
+ foldLine.addFold(fold);
14371
+ added = true;
14372
+ break;
14373
+ } else if (startRow == foldLine.end.row) {
14374
+ foldLine.addFold(fold);
14375
+ added = true;
14376
+ if (!fold.sameRow) {
14377
+ var foldLineNext = foldData[i + 1];
14378
+ if (foldLineNext && foldLineNext.start.row == endRow) {
14379
+ foldLine.merge(foldLineNext);
14380
+ break;
14381
+ }
14382
+ }
14383
+ break;
14384
+ } else if (endRow <= foldLine.start.row) {
14385
+ break;
14386
+ }
14387
+ }
14388
+
14389
+ if (!added)
14390
+ foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
14391
+
14392
+ if (this.$useWrapMode)
14393
+ this.$updateWrapData(foldLine.start.row, foldLine.start.row);
14394
+ else
14395
+ this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);
14396
+ this.$modified = true;
14397
+ this._emit("changeFold", { data: fold, action: "add" });
14398
+
14399
+ return fold;
14400
+ };
14401
+
14402
+ this.addFolds = function(folds) {
14403
+ folds.forEach(function(fold) {
14404
+ this.addFold(fold);
14405
+ }, this);
14406
+ };
14407
+
14408
+ this.removeFold = function(fold) {
14409
+ var foldLine = fold.foldLine;
14410
+ var startRow = foldLine.start.row;
14411
+ var endRow = foldLine.end.row;
14412
+
14413
+ var foldLines = this.$foldData;
14414
+ var folds = foldLine.folds;
14415
+ if (folds.length == 1) {
14416
+ foldLines.splice(foldLines.indexOf(foldLine), 1);
14417
+ } else
14418
+ if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {
14419
+ folds.pop();
14420
+ foldLine.end.row = folds[folds.length - 1].end.row;
14421
+ foldLine.end.column = folds[folds.length - 1].end.column;
14422
+ } else
14423
+ if (foldLine.range.isStart(fold.start.row, fold.start.column)) {
14424
+ folds.shift();
14425
+ foldLine.start.row = folds[0].start.row;
14426
+ foldLine.start.column = folds[0].start.column;
14427
+ } else
14428
+ if (fold.sameRow) {
14429
+ folds.splice(folds.indexOf(fold), 1);
14430
+ } else
14431
+ {
14432
+ var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
14433
+ folds = newFoldLine.folds;
14434
+ folds.shift();
14435
+ newFoldLine.start.row = folds[0].start.row;
14436
+ newFoldLine.start.column = folds[0].start.column;
14437
+ }
14438
+
14439
+ if (!this.$updating) {
14440
+ if (this.$useWrapMode)
14441
+ this.$updateWrapData(startRow, endRow);
14442
+ else
14443
+ this.$updateRowLengthCache(startRow, endRow);
14444
+ }
14445
+ this.$modified = true;
14446
+ this._emit("changeFold", { data: fold, action: "remove" });
14447
+ };
14448
+
14449
+ this.removeFolds = function(folds) {
14450
+ var cloneFolds = [];
14451
+ for (var i = 0; i < folds.length; i++) {
14452
+ cloneFolds.push(folds[i]);
14453
+ }
14454
+
14455
+ cloneFolds.forEach(function(fold) {
14456
+ this.removeFold(fold);
14457
+ }, this);
14458
+ this.$modified = true;
14459
+ };
14460
+
14461
+ this.expandFold = function(fold) {
14462
+ this.removeFold(fold);
14463
+ fold.subFolds.forEach(function(subFold) {
14464
+ fold.restoreRange(subFold);
14465
+ this.addFold(subFold);
14466
+ }, this);
14467
+ if (fold.collapseChildren > 0) {
14468
+ this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1);
14469
+ }
14470
+ fold.subFolds = [];
14471
+ };
14472
+
14473
+ this.expandFolds = function(folds) {
14474
+ folds.forEach(function(fold) {
14475
+ this.expandFold(fold);
14476
+ }, this);
14477
+ };
14478
+
14479
+ this.unfold = function(location, expandInner) {
14480
+ var range, folds;
14481
+ if (location == null) {
14482
+ range = new Range(0, 0, this.getLength(), 0);
14483
+ expandInner = true;
14484
+ } else if (typeof location == "number")
14485
+ range = new Range(location, 0, location, this.getLine(location).length);
14486
+ else if ("row" in location)
14487
+ range = Range.fromPoints(location, location);
14488
+ else
14489
+ range = location;
14490
+
14491
+ folds = this.getFoldsInRangeList(range);
14492
+ if (expandInner) {
14493
+ this.removeFolds(folds);
14494
+ } else {
14495
+ var subFolds = folds;
14496
+ while (subFolds.length) {
14497
+ this.expandFolds(subFolds);
14498
+ subFolds = this.getFoldsInRangeList(range);
14499
+ }
14500
+ }
14501
+ if (folds.length)
14502
+ return folds;
14503
+ };
14504
+ this.isRowFolded = function(docRow, startFoldRow) {
14505
+ return !!this.getFoldLine(docRow, startFoldRow);
14506
+ };
14507
+
14508
+ this.getRowFoldEnd = function(docRow, startFoldRow) {
14509
+ var foldLine = this.getFoldLine(docRow, startFoldRow);
14510
+ return foldLine ? foldLine.end.row : docRow;
14511
+ };
14512
+
14513
+ this.getRowFoldStart = function(docRow, startFoldRow) {
14514
+ var foldLine = this.getFoldLine(docRow, startFoldRow);
14515
+ return foldLine ? foldLine.start.row : docRow;
14516
+ };
14517
+
14518
+ this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
14519
+ if (startRow == null)
14520
+ startRow = foldLine.start.row;
14521
+ if (startColumn == null)
14522
+ startColumn = 0;
14523
+ if (endRow == null)
14524
+ endRow = foldLine.end.row;
14525
+ if (endColumn == null)
14526
+ endColumn = this.getLine(endRow).length;
14527
+ var doc = this.doc;
14528
+ var textLine = "";
14529
+
14530
+ foldLine.walk(function(placeholder, row, column, lastColumn) {
14531
+ if (row < startRow)
14532
+ return;
14533
+ if (row == startRow) {
14534
+ if (column < startColumn)
14535
+ return;
14536
+ lastColumn = Math.max(startColumn, lastColumn);
14537
+ }
14538
+
14539
+ if (placeholder != null) {
14540
+ textLine += placeholder;
14541
+ } else {
14542
+ textLine += doc.getLine(row).substring(lastColumn, column);
14543
+ }
14544
+ }, endRow, endColumn);
14545
+ return textLine;
14546
+ };
14547
+
14548
+ this.getDisplayLine = function(row, endColumn, startRow, startColumn) {
14549
+ var foldLine = this.getFoldLine(row);
14550
+
14551
+ if (!foldLine) {
14552
+ var line;
14553
+ line = this.doc.getLine(row);
14554
+ return line.substring(startColumn || 0, endColumn || line.length);
14555
+ } else {
14556
+ return this.getFoldDisplayLine(
14557
+ foldLine, row, endColumn, startRow, startColumn);
14558
+ }
14559
+ };
14560
+
14561
+ this.$cloneFoldData = function() {
14562
+ var fd = [];
14563
+ fd = this.$foldData.map(function(foldLine) {
14564
+ var folds = foldLine.folds.map(function(fold) {
14565
+ return fold.clone();
14566
+ });
14567
+ return new FoldLine(fd, folds);
14568
+ });
14569
+
14570
+ return fd;
14571
+ };
14572
+
14573
+ this.toggleFold = function(tryToUnfold) {
14574
+ var selection = this.selection;
14575
+ var range = selection.getRange();
14576
+ var fold;
14577
+ var bracketPos;
14578
+
14579
+ if (range.isEmpty()) {
14580
+ var cursor = range.start;
14581
+ fold = this.getFoldAt(cursor.row, cursor.column);
14582
+
14583
+ if (fold) {
14584
+ this.expandFold(fold);
14585
+ return;
14586
+ } else if (bracketPos = this.findMatchingBracket(cursor)) {
14587
+ if (range.comparePoint(bracketPos) == 1) {
14588
+ range.end = bracketPos;
14589
+ } else {
14590
+ range.start = bracketPos;
14591
+ range.start.column++;
14592
+ range.end.column--;
14593
+ }
14594
+ } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {
14595
+ if (range.comparePoint(bracketPos) == 1)
14596
+ range.end = bracketPos;
14597
+ else
14598
+ range.start = bracketPos;
14599
+
14600
+ range.start.column++;
14601
+ } else {
14602
+ range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
14603
+ }
14604
+ } else {
14605
+ var folds = this.getFoldsInRange(range);
14606
+ if (tryToUnfold && folds.length) {
14607
+ this.expandFolds(folds);
14608
+ return;
14609
+ } else if (folds.length == 1 ) {
14610
+ fold = folds[0];
14611
+ }
14612
+ }
14613
+
14614
+ if (!fold)
14615
+ fold = this.getFoldAt(range.start.row, range.start.column);
14616
+
14617
+ if (fold && fold.range.toString() == range.toString()) {
14618
+ this.expandFold(fold);
14619
+ return;
14620
+ }
14621
+
14622
+ var placeholder = "...";
14623
+ if (!range.isMultiLine()) {
14624
+ placeholder = this.getTextRange(range);
14625
+ if(placeholder.length < 4)
14626
+ return;
14627
+ placeholder = placeholder.trim().substring(0, 2) + "..";
14628
+ }
14629
+
14630
+ this.addFold(placeholder, range);
14631
+ };
14632
+
14633
+ this.getCommentFoldRange = function(row, column, dir) {
14634
+ var iterator = new TokenIterator(this, row, column);
14635
+ var token = iterator.getCurrentToken();
14636
+ if (token && /^comment|string/.test(token.type)) {
14637
+ var range = new Range();
14638
+ var re = new RegExp(token.type.replace(/\..*/, "\\."));
14639
+ if (dir != 1) {
14640
+ do {
14641
+ token = iterator.stepBackward();
14642
+ } while(token && re.test(token.type));
14643
+ iterator.stepForward();
14644
+ }
14645
+
14646
+ range.start.row = iterator.getCurrentTokenRow();
14647
+ range.start.column = iterator.getCurrentTokenColumn() + 2;
14648
+
14649
+ iterator = new TokenIterator(this, row, column);
14650
+
14651
+ if (dir != -1) {
14652
+ do {
14653
+ token = iterator.stepForward();
14654
+ } while(token && re.test(token.type));
14655
+ token = iterator.stepBackward();
14656
+ } else
14657
+ token = iterator.getCurrentToken();
14658
+
14659
+ range.end.row = iterator.getCurrentTokenRow();
14660
+ range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2;
14661
+ return range;
14662
+ }
14663
+ };
14664
+
14665
+ this.foldAll = function(startRow, endRow, depth) {
14666
+ if (depth == undefined)
14667
+ depth = 100000; // JSON.stringify doesn't hanle Infinity
14668
+ var foldWidgets = this.foldWidgets;
14669
+ if (!foldWidgets)
14670
+ return; // mode doesn't support folding
14671
+ endRow = endRow || this.getLength();
14672
+ startRow = startRow || 0;
14673
+ for (var row = startRow; row < endRow; row++) {
14674
+ if (foldWidgets[row] == null)
14675
+ foldWidgets[row] = this.getFoldWidget(row);
14676
+ if (foldWidgets[row] != "start")
14677
+ continue;
14678
+
14679
+ var range = this.getFoldWidgetRange(row);
14680
+ if (range && range.isMultiLine()
14681
+ && range.end.row <= endRow
14682
+ && range.start.row >= startRow
14683
+ ) {
14684
+ row = range.end.row;
14685
+ try {
14686
+ var fold = this.addFold("...", range);
14687
+ if (fold)
14688
+ fold.collapseChildren = depth;
14689
+ } catch(e) {}
14690
+ }
14691
+ }
14692
+ };
14693
+ this.$foldStyles = {
14694
+ "manual": 1,
14695
+ "markbegin": 1,
14696
+ "markbeginend": 1
14697
+ };
14698
+ this.$foldStyle = "markbegin";
14699
+ this.setFoldStyle = function(style) {
14700
+ if (!this.$foldStyles[style])
14701
+ throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]");
14702
+
14703
+ if (this.$foldStyle == style)
14704
+ return;
14705
+
14706
+ this.$foldStyle = style;
14707
+
14708
+ if (style == "manual")
14709
+ this.unfold();
14710
+ var mode = this.$foldMode;
14711
+ this.$setFolding(null);
14712
+ this.$setFolding(mode);
14713
+ };
14714
+
14715
+ this.$setFolding = function(foldMode) {
14716
+ if (this.$foldMode == foldMode)
14717
+ return;
14718
+
14719
+ this.$foldMode = foldMode;
14720
+
14721
+ this.removeListener('change', this.$updateFoldWidgets);
14722
+ this._emit("changeAnnotation");
14723
+
14724
+ if (!foldMode || this.$foldStyle == "manual") {
14725
+ this.foldWidgets = null;
14726
+ return;
14727
+ }
14728
+
14729
+ this.foldWidgets = [];
14730
+ this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle);
14731
+ this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
14732
+
14733
+ this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
14734
+ this.on('change', this.$updateFoldWidgets);
14735
+
14736
+ };
14737
+
14738
+ this.getParentFoldRangeData = function (row, ignoreCurrent) {
14739
+ var fw = this.foldWidgets;
14740
+ if (!fw || (ignoreCurrent && fw[row]))
14741
+ return {};
14742
+
14743
+ var i = row - 1, firstRange;
14744
+ while (i >= 0) {
14745
+ var c = fw[i];
14746
+ if (c == null)
14747
+ c = fw[i] = this.getFoldWidget(i);
14748
+
14749
+ if (c == "start") {
14750
+ var range = this.getFoldWidgetRange(i);
14751
+ if (!firstRange)
14752
+ firstRange = range;
14753
+ if (range && range.end.row >= row)
14754
+ break;
14755
+ }
14756
+ i--;
14757
+ }
14758
+
14759
+ return {
14760
+ range: i !== -1 && range,
14761
+ firstRange: firstRange
14762
+ };
14763
+ }
14764
+
14765
+ this.onFoldWidgetClick = function(row, e) {
14766
+ e = e.domEvent;
14767
+ var options = {
14768
+ children: e.shiftKey,
14769
+ all: e.ctrlKey || e.metaKey,
14770
+ siblings: e.altKey
14771
+ };
14772
+
14773
+ var range = this.$toggleFoldWidget(row, options);
14774
+ if (!range) {
14775
+ var el = (e.target || e.srcElement)
14776
+ if (el && /ace_fold-widget/.test(el.className))
14777
+ el.className += " ace_invalid";
14778
+ }
14779
+ };
14780
+
14781
+ this.$toggleFoldWidget = function(row, options) {
14782
+ if (!this.getFoldWidget)
14783
+ return;
14784
+ var type = this.getFoldWidget(row);
14785
+ var line = this.getLine(row);
14786
+
14787
+ var dir = type === "end" ? -1 : 1;
14788
+ var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);
14789
+
14790
+ if (fold) {
14791
+ if (options.children || options.all)
14792
+ this.removeFold(fold);
14793
+ else
14794
+ this.expandFold(fold);
14795
+ return;
14796
+ }
14797
+
14798
+ var range = this.getFoldWidgetRange(row, true);
14799
+ if (range && !range.isMultiLine()) {
14800
+ fold = this.getFoldAt(range.start.row, range.start.column, 1);
14801
+ if (fold && range.isEqual(fold.range)) {
14802
+ this.removeFold(fold);
14803
+ return;
14804
+ }
14805
+ }
14806
+
14807
+ if (options.siblings) {
14808
+ var data = this.getParentFoldRangeData(row);
14809
+ if (data.range) {
14810
+ var startRow = data.range.start.row + 1;
14811
+ var endRow = data.range.end.row;
14812
+ }
14813
+ this.foldAll(startRow, endRow, options.all ? 10000 : 0);
14814
+ } else if (options.children) {
14815
+ endRow = range ? range.end.row : this.getLength();
14816
+ this.foldAll(row + 1, range.end.row, options.all ? 10000 : 0);
14817
+ } else if (range) {
14818
+ if (options.all)
14819
+ range.collapseChildren = 10000;
14820
+ this.addFold("...", range);
14821
+ }
14822
+
14823
+ return range;
14824
+ };
14825
+
14826
+
14827
+
14828
+ this.toggleFoldWidget = function(toggleParent) {
14829
+ var row = this.selection.getCursor().row;
14830
+ row = this.getRowFoldStart(row);
14831
+ var range = this.$toggleFoldWidget(row, {});
14832
+
14833
+ if (range)
14834
+ return;
14835
+ var data = this.getParentFoldRangeData(row, true);
14836
+ range = data.range || data.firstRange;
14837
+
14838
+ if (range) {
14839
+ row = range.start.row;
14840
+ var fold = this.getFoldAt(row, this.getLine(row).length, 1);
14841
+
14842
+ if (fold) {
14843
+ this.removeFold(fold);
14844
+ } else {
14845
+ this.addFold("...", range);
14846
+ }
14847
+ }
14848
+ };
14849
+
14850
+ this.updateFoldWidgets = function(e) {
14851
+ var delta = e.data;
14852
+ var range = delta.range;
14853
+ var firstRow = range.start.row;
14854
+ var len = range.end.row - firstRow;
14855
+
14856
+ if (len === 0) {
14857
+ this.foldWidgets[firstRow] = null;
14858
+ } else if (delta.action == "removeText" || delta.action == "removeLines") {
14859
+ this.foldWidgets.splice(firstRow, len + 1, null);
14860
+ } else {
14861
+ var args = Array(len + 1);
14862
+ args.unshift(firstRow, 1);
14863
+ this.foldWidgets.splice.apply(this.foldWidgets, args);
14864
+ }
14865
+ };
14866
+
14867
+ }
14868
+
14869
+ exports.Folding = Folding;
14870
+
14871
+ });
14872
+
14873
+ ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(acequire, exports, module) {
14874
+ "use strict";
14875
+
14876
+ var TokenIterator = acequire("../token_iterator").TokenIterator;
14877
+ var Range = acequire("../range").Range;
14878
+
14879
+
14880
+ function BracketMatch() {
14881
+
14882
+ this.findMatchingBracket = function(position, chr) {
14883
+ if (position.column == 0) return null;
14884
+
14885
+ var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1);
14886
+ if (charBeforeCursor == "") return null;
14887
+
14888
+ var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
14889
+ if (!match)
14890
+ return null;
14891
+
14892
+ if (match[1])
14893
+ return this.$findClosingBracket(match[1], position);
14894
+ else
14895
+ return this.$findOpeningBracket(match[2], position);
14896
+ };
14897
+
14898
+ this.getBracketRange = function(pos) {
14899
+ var line = this.getLine(pos.row);
14900
+ var before = true, range;
14901
+
14902
+ var chr = line.charAt(pos.column-1);
14903
+ var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
14904
+ if (!match) {
14905
+ chr = line.charAt(pos.column);
14906
+ pos = {row: pos.row, column: pos.column + 1};
14907
+ match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
14908
+ before = false;
14909
+ }
14910
+ if (!match)
14911
+ return null;
14912
+
14913
+ if (match[1]) {
14914
+ var bracketPos = this.$findClosingBracket(match[1], pos);
14915
+ if (!bracketPos)
14916
+ return null;
14917
+ range = Range.fromPoints(pos, bracketPos);
14918
+ if (!before) {
14919
+ range.end.column++;
14920
+ range.start.column--;
14921
+ }
14922
+ range.cursor = range.end;
14923
+ } else {
14924
+ var bracketPos = this.$findOpeningBracket(match[2], pos);
14925
+ if (!bracketPos)
14926
+ return null;
14927
+ range = Range.fromPoints(bracketPos, pos);
14928
+ if (!before) {
14929
+ range.start.column++;
14930
+ range.end.column--;
14931
+ }
14932
+ range.cursor = range.start;
14933
+ }
14934
+
14935
+ return range;
14936
+ };
14937
+
14938
+ this.$brackets = {
14939
+ ")": "(",
14940
+ "(": ")",
14941
+ "]": "[",
14942
+ "[": "]",
14943
+ "{": "}",
14944
+ "}": "{"
14945
+ };
14946
+
14947
+ this.$findOpeningBracket = function(bracket, position, typeRe) {
14948
+ var openBracket = this.$brackets[bracket];
14949
+ var depth = 1;
14950
+
14951
+ var iterator = new TokenIterator(this, position.row, position.column);
14952
+ var token = iterator.getCurrentToken();
14953
+ if (!token)
14954
+ token = iterator.stepForward();
14955
+ if (!token)
14956
+ return;
14957
+
14958
+ if (!typeRe){
14959
+ typeRe = new RegExp(
14960
+ "(\\.?" +
14961
+ token.type.replace(".", "\\.").replace("rparen", ".paren")
14962
+ .replace(/\b(?:end|start|begin)\b/, "")
14963
+ + ")+"
14964
+ );
14965
+ }
14966
+ var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;
14967
+ var value = token.value;
14968
+
14969
+ while (true) {
14970
+
14971
+ while (valueIndex >= 0) {
14972
+ var chr = value.charAt(valueIndex);
14973
+ if (chr == openBracket) {
14974
+ depth -= 1;
14975
+ if (depth == 0) {
14976
+ return {row: iterator.getCurrentTokenRow(),
14977
+ column: valueIndex + iterator.getCurrentTokenColumn()};
14978
+ }
14979
+ }
14980
+ else if (chr == bracket) {
14981
+ depth += 1;
14982
+ }
14983
+ valueIndex -= 1;
14984
+ }
14985
+ do {
14986
+ token = iterator.stepBackward();
14987
+ } while (token && !typeRe.test(token.type));
14988
+
14989
+ if (token == null)
14990
+ break;
14991
+
14992
+ value = token.value;
14993
+ valueIndex = value.length - 1;
14994
+ }
14995
+
14996
+ return null;
14997
+ };
14998
+
14999
+ this.$findClosingBracket = function(bracket, position, typeRe) {
15000
+ var closingBracket = this.$brackets[bracket];
15001
+ var depth = 1;
15002
+
15003
+ var iterator = new TokenIterator(this, position.row, position.column);
15004
+ var token = iterator.getCurrentToken();
15005
+ if (!token)
15006
+ token = iterator.stepForward();
15007
+ if (!token)
15008
+ return;
15009
+
15010
+ if (!typeRe){
15011
+ typeRe = new RegExp(
15012
+ "(\\.?" +
15013
+ token.type.replace(".", "\\.").replace("lparen", ".paren")
15014
+ .replace(/\b(?:end|start|begin)\b/, "")
15015
+ + ")+"
15016
+ );
15017
+ }
15018
+ var valueIndex = position.column - iterator.getCurrentTokenColumn();
15019
+
15020
+ while (true) {
15021
+
15022
+ var value = token.value;
15023
+ var valueLength = value.length;
15024
+ while (valueIndex < valueLength) {
15025
+ var chr = value.charAt(valueIndex);
15026
+ if (chr == closingBracket) {
15027
+ depth -= 1;
15028
+ if (depth == 0) {
15029
+ return {row: iterator.getCurrentTokenRow(),
15030
+ column: valueIndex + iterator.getCurrentTokenColumn()};
15031
+ }
15032
+ }
15033
+ else if (chr == bracket) {
15034
+ depth += 1;
15035
+ }
15036
+ valueIndex += 1;
15037
+ }
15038
+ do {
15039
+ token = iterator.stepForward();
15040
+ } while (token && !typeRe.test(token.type));
15041
+
15042
+ if (token == null)
15043
+ break;
15044
+
15045
+ valueIndex = 0;
15046
+ }
15047
+
15048
+ return null;
15049
+ };
15050
+ }
15051
+ exports.BracketMatch = BracketMatch;
15052
+
15053
+ });
15054
+
15055
+ ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(acequire, exports, module) {
15056
+ "use strict";
15057
+
15058
+ var oop = acequire("./lib/oop");
15059
+ var lang = acequire("./lib/lang");
15060
+ var config = acequire("./config");
15061
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
15062
+ var Selection = acequire("./selection").Selection;
15063
+ var TextMode = acequire("./mode/text").Mode;
15064
+ var Range = acequire("./range").Range;
15065
+ var Document = acequire("./document").Document;
15066
+ var BackgroundTokenizer = acequire("./background_tokenizer").BackgroundTokenizer;
15067
+ var SearchHighlight = acequire("./search_highlight").SearchHighlight;
15068
+
15069
+ var EditSession = function(text, mode) {
15070
+ this.$breakpoints = [];
15071
+ this.$decorations = [];
15072
+ this.$frontMarkers = {};
15073
+ this.$backMarkers = {};
15074
+ this.$markerId = 1;
15075
+ this.$undoSelect = true;
15076
+
15077
+ this.$foldData = [];
15078
+ this.$foldData.toString = function() {
15079
+ return this.join("\n");
15080
+ }
15081
+ this.on("changeFold", this.onChangeFold.bind(this));
15082
+ this.$onChange = this.onChange.bind(this);
15083
+
15084
+ if (typeof text != "object" || !text.getLine)
15085
+ text = new Document(text);
15086
+
15087
+ this.setDocument(text);
15088
+ this.selection = new Selection(this);
15089
+
15090
+ config.resetOptions(this);
15091
+ this.setMode(mode);
15092
+ config._signal("session", this);
15093
+ };
15094
+
15095
+
15096
+ (function() {
15097
+
15098
+ oop.implement(this, EventEmitter);
15099
+ this.setDocument = function(doc) {
15100
+ if (this.doc)
15101
+ this.doc.removeListener("change", this.$onChange);
15102
+
15103
+ this.doc = doc;
15104
+ doc.on("change", this.$onChange);
15105
+
15106
+ if (this.bgTokenizer)
15107
+ this.bgTokenizer.setDocument(this.getDocument());
15108
+
15109
+ this.resetCaches();
15110
+ };
15111
+ this.getDocument = function() {
15112
+ return this.doc;
15113
+ };
15114
+ this.$resetRowCache = function(docRow) {
15115
+ if (!docRow) {
15116
+ this.$docRowCache = [];
15117
+ this.$screenRowCache = [];
15118
+ return;
15119
+ }
15120
+ var l = this.$docRowCache.length;
15121
+ var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1;
15122
+ if (l > i) {
15123
+ this.$docRowCache.splice(i, l);
15124
+ this.$screenRowCache.splice(i, l);
15125
+ }
15126
+ };
15127
+
15128
+ this.$getRowCacheIndex = function(cacheArray, val) {
15129
+ var low = 0;
15130
+ var hi = cacheArray.length - 1;
15131
+
15132
+ while (low <= hi) {
15133
+ var mid = (low + hi) >> 1;
15134
+ var c = cacheArray[mid];
15135
+
15136
+ if (val > c)
15137
+ low = mid + 1;
15138
+ else if (val < c)
15139
+ hi = mid - 1;
15140
+ else
15141
+ return mid;
15142
+ }
15143
+
15144
+ return low -1;
15145
+ };
15146
+
15147
+ this.resetCaches = function() {
15148
+ this.$modified = true;
15149
+ this.$wrapData = [];
15150
+ this.$rowLengthCache = [];
15151
+ this.$resetRowCache(0);
15152
+ if (this.bgTokenizer)
15153
+ this.bgTokenizer.start(0);
15154
+ };
15155
+
15156
+ this.onChangeFold = function(e) {
15157
+ var fold = e.data;
15158
+ this.$resetRowCache(fold.start.row);
15159
+ };
15160
+
15161
+ this.onChange = function(e) {
15162
+ var delta = e.data;
15163
+ this.$modified = true;
15164
+
15165
+ this.$resetRowCache(delta.range.start.row);
15166
+
15167
+ var removedFolds = this.$updateInternalDataOnChange(e);
15168
+ if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
15169
+ this.$deltasDoc.push(delta);
15170
+ if (removedFolds && removedFolds.length != 0) {
15171
+ this.$deltasFold.push({
15172
+ action: "removeFolds",
15173
+ folds: removedFolds
15174
+ });
15175
+ }
15176
+
15177
+ this.$informUndoManager.schedule();
15178
+ }
15179
+
15180
+ this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
15181
+ this._signal("change", e);
15182
+ };
15183
+ this.setValue = function(text) {
15184
+ this.doc.setValue(text);
15185
+ this.selection.moveTo(0, 0);
15186
+
15187
+ this.$resetRowCache(0);
15188
+ this.$deltas = [];
15189
+ this.$deltasDoc = [];
15190
+ this.$deltasFold = [];
15191
+ this.setUndoManager(this.$undoManager);
15192
+ this.getUndoManager().reset();
15193
+ };
15194
+ this.getValue =
15195
+ this.toString = function() {
15196
+ return this.doc.getValue();
15197
+ };
15198
+ this.getSelection = function() {
15199
+ return this.selection;
15200
+ };
15201
+ this.getState = function(row) {
15202
+ return this.bgTokenizer.getState(row);
15203
+ };
15204
+ this.getTokens = function(row) {
15205
+ return this.bgTokenizer.getTokens(row);
15206
+ };
15207
+ this.getTokenAt = function(row, column) {
15208
+ var tokens = this.bgTokenizer.getTokens(row);
15209
+ var token, c = 0;
15210
+ if (column == null) {
15211
+ i = tokens.length - 1;
15212
+ c = this.getLine(row).length;
15213
+ } else {
15214
+ for (var i = 0; i < tokens.length; i++) {
15215
+ c += tokens[i].value.length;
15216
+ if (c >= column)
15217
+ break;
15218
+ }
15219
+ }
15220
+ token = tokens[i];
15221
+ if (!token)
15222
+ return null;
15223
+ token.index = i;
15224
+ token.start = c - token.value.length;
15225
+ return token;
15226
+ };
15227
+ this.setUndoManager = function(undoManager) {
15228
+ this.$undoManager = undoManager;
15229
+ this.$deltas = [];
15230
+ this.$deltasDoc = [];
15231
+ this.$deltasFold = [];
15232
+
15233
+ if (this.$informUndoManager)
15234
+ this.$informUndoManager.cancel();
15235
+
15236
+ if (undoManager) {
15237
+ var self = this;
15238
+
15239
+ this.$syncInformUndoManager = function() {
15240
+ self.$informUndoManager.cancel();
15241
+
15242
+ if (self.$deltasFold.length) {
15243
+ self.$deltas.push({
15244
+ group: "fold",
15245
+ deltas: self.$deltasFold
15246
+ });
15247
+ self.$deltasFold = [];
15248
+ }
15249
+
15250
+ if (self.$deltasDoc.length) {
15251
+ self.$deltas.push({
15252
+ group: "doc",
15253
+ deltas: self.$deltasDoc
15254
+ });
15255
+ self.$deltasDoc = [];
15256
+ }
15257
+
15258
+ if (self.$deltas.length > 0) {
15259
+ undoManager.execute({
15260
+ action: "aceupdate",
15261
+ args: [self.$deltas, self],
15262
+ merge: self.mergeUndoDeltas
15263
+ });
15264
+ }
15265
+ self.mergeUndoDeltas = false;
15266
+ self.$deltas = [];
15267
+ };
15268
+ this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
15269
+ }
15270
+ };
15271
+ this.markUndoGroup = function() {
15272
+ if (this.$syncInformUndoManager)
15273
+ this.$syncInformUndoManager();
15274
+ };
15275
+
15276
+ this.$defaultUndoManager = {
15277
+ undo: function() {},
15278
+ redo: function() {},
15279
+ reset: function() {}
15280
+ };
15281
+ this.getUndoManager = function() {
15282
+ return this.$undoManager || this.$defaultUndoManager;
15283
+ };
15284
+ this.getTabString = function() {
15285
+ if (this.getUseSoftTabs()) {
15286
+ return lang.stringRepeat(" ", this.getTabSize());
15287
+ } else {
15288
+ return "\t";
15289
+ }
15290
+ };
15291
+ this.setUseSoftTabs = function(val) {
15292
+ this.setOption("useSoftTabs", val);
15293
+ };
15294
+ this.getUseSoftTabs = function() {
15295
+ return this.$useSoftTabs && !this.$mode.$indentWithTabs;
15296
+ };
15297
+ this.setTabSize = function(tabSize) {
15298
+ this.setOption("tabSize", tabSize);
15299
+ };
15300
+ this.getTabSize = function() {
15301
+ return this.$tabSize;
15302
+ };
15303
+ this.isTabStop = function(position) {
15304
+ return this.$useSoftTabs && (position.column % this.$tabSize === 0);
15305
+ };
15306
+
15307
+ this.$overwrite = false;
15308
+ this.setOverwrite = function(overwrite) {
15309
+ this.setOption("overwrite", overwrite);
15310
+ };
15311
+ this.getOverwrite = function() {
15312
+ return this.$overwrite;
15313
+ };
15314
+ this.toggleOverwrite = function() {
15315
+ this.setOverwrite(!this.$overwrite);
15316
+ };
15317
+ this.addGutterDecoration = function(row, className) {
15318
+ if (!this.$decorations[row])
15319
+ this.$decorations[row] = "";
15320
+ this.$decorations[row] += " " + className;
15321
+ this._signal("changeBreakpoint", {});
15322
+ };
15323
+ this.removeGutterDecoration = function(row, className) {
15324
+ this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, "");
15325
+ this._signal("changeBreakpoint", {});
15326
+ };
15327
+ this.getBreakpoints = function() {
15328
+ return this.$breakpoints;
15329
+ };
15330
+ this.setBreakpoints = function(rows) {
15331
+ this.$breakpoints = [];
15332
+ for (var i=0; i<rows.length; i++) {
15333
+ this.$breakpoints[rows[i]] = "ace_breakpoint";
15334
+ }
15335
+ this._signal("changeBreakpoint", {});
15336
+ };
15337
+ this.clearBreakpoints = function() {
15338
+ this.$breakpoints = [];
15339
+ this._signal("changeBreakpoint", {});
15340
+ };
15341
+ this.setBreakpoint = function(row, className) {
15342
+ if (className === undefined)
15343
+ className = "ace_breakpoint";
15344
+ if (className)
15345
+ this.$breakpoints[row] = className;
15346
+ else
15347
+ delete this.$breakpoints[row];
15348
+ this._signal("changeBreakpoint", {});
15349
+ };
15350
+ this.clearBreakpoint = function(row) {
15351
+ delete this.$breakpoints[row];
15352
+ this._signal("changeBreakpoint", {});
15353
+ };
15354
+ this.addMarker = function(range, clazz, type, inFront) {
15355
+ var id = this.$markerId++;
15356
+
15357
+ var marker = {
15358
+ range : range,
15359
+ type : type || "line",
15360
+ renderer: typeof type == "function" ? type : null,
15361
+ clazz : clazz,
15362
+ inFront: !!inFront,
15363
+ id: id
15364
+ };
15365
+
15366
+ if (inFront) {
15367
+ this.$frontMarkers[id] = marker;
15368
+ this._signal("changeFrontMarker");
15369
+ } else {
15370
+ this.$backMarkers[id] = marker;
15371
+ this._signal("changeBackMarker");
15372
+ }
15373
+
15374
+ return id;
15375
+ };
15376
+ this.addDynamicMarker = function(marker, inFront) {
15377
+ if (!marker.update)
15378
+ return;
15379
+ var id = this.$markerId++;
15380
+ marker.id = id;
15381
+ marker.inFront = !!inFront;
15382
+
15383
+ if (inFront) {
15384
+ this.$frontMarkers[id] = marker;
15385
+ this._signal("changeFrontMarker");
15386
+ } else {
15387
+ this.$backMarkers[id] = marker;
15388
+ this._signal("changeBackMarker");
15389
+ }
15390
+
15391
+ return marker;
15392
+ };
15393
+ this.removeMarker = function(markerId) {
15394
+ var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
15395
+ if (!marker)
15396
+ return;
15397
+
15398
+ var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
15399
+ if (marker) {
15400
+ delete (markers[markerId]);
15401
+ this._signal(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
15402
+ }
15403
+ };
15404
+ this.getMarkers = function(inFront) {
15405
+ return inFront ? this.$frontMarkers : this.$backMarkers;
15406
+ };
15407
+
15408
+ this.highlight = function(re) {
15409
+ if (!this.$searchHighlight) {
15410
+ var highlight = new SearchHighlight(null, "ace_selected-word", "text");
15411
+ this.$searchHighlight = this.addDynamicMarker(highlight);
15412
+ }
15413
+ this.$searchHighlight.setRegexp(re);
15414
+ };
15415
+ this.highlightLines = function(startRow, endRow, clazz, inFront) {
15416
+ if (typeof endRow != "number") {
15417
+ clazz = endRow;
15418
+ endRow = startRow;
15419
+ }
15420
+ if (!clazz)
15421
+ clazz = "ace_step";
15422
+
15423
+ var range = new Range(startRow, 0, endRow, Infinity);
15424
+ range.id = this.addMarker(range, clazz, "fullLine", inFront);
15425
+ return range;
15426
+ };
15427
+ this.setAnnotations = function(annotations) {
15428
+ this.$annotations = annotations;
15429
+ this._signal("changeAnnotation", {});
15430
+ };
15431
+ this.getAnnotations = function() {
15432
+ return this.$annotations || [];
15433
+ };
15434
+ this.clearAnnotations = function() {
15435
+ this.setAnnotations([]);
15436
+ };
15437
+ this.$detectNewLine = function(text) {
15438
+ var match = text.match(/^.*?(\r?\n)/m);
15439
+ if (match) {
15440
+ this.$autoNewLine = match[1];
15441
+ } else {
15442
+ this.$autoNewLine = "\n";
15443
+ }
15444
+ };
15445
+ this.getWordRange = function(row, column) {
15446
+ var line = this.getLine(row);
15447
+
15448
+ var inToken = false;
15449
+ if (column > 0)
15450
+ inToken = !!line.charAt(column - 1).match(this.tokenRe);
15451
+
15452
+ if (!inToken)
15453
+ inToken = !!line.charAt(column).match(this.tokenRe);
15454
+
15455
+ if (inToken)
15456
+ var re = this.tokenRe;
15457
+ else if (/^\s+$/.test(line.slice(column-1, column+1)))
15458
+ var re = /\s/;
15459
+ else
15460
+ var re = this.nonTokenRe;
15461
+
15462
+ var start = column;
15463
+ if (start > 0) {
15464
+ do {
15465
+ start--;
15466
+ }
15467
+ while (start >= 0 && line.charAt(start).match(re));
15468
+ start++;
15469
+ }
15470
+
15471
+ var end = column;
15472
+ while (end < line.length && line.charAt(end).match(re)) {
15473
+ end++;
15474
+ }
15475
+
15476
+ return new Range(row, start, row, end);
15477
+ };
15478
+ this.getAWordRange = function(row, column) {
15479
+ var wordRange = this.getWordRange(row, column);
15480
+ var line = this.getLine(wordRange.end.row);
15481
+
15482
+ while (line.charAt(wordRange.end.column).match(/[ \t]/)) {
15483
+ wordRange.end.column += 1;
15484
+ }
15485
+ return wordRange;
15486
+ };
15487
+ this.setNewLineMode = function(newLineMode) {
15488
+ this.doc.setNewLineMode(newLineMode);
15489
+ };
15490
+ this.getNewLineMode = function() {
15491
+ return this.doc.getNewLineMode();
15492
+ };
15493
+ this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); };
15494
+ this.getUseWorker = function() { return this.$useWorker; };
15495
+ this.onReloadTokenizer = function(e) {
15496
+ var rows = e.data;
15497
+ this.bgTokenizer.start(rows.first);
15498
+ this._signal("tokenizerUpdate", e);
15499
+ };
15500
+
15501
+ this.$modes = {};
15502
+ this.$mode = null;
15503
+ this.$modeId = null;
15504
+ this.setMode = function(mode, cb) {
15505
+ if (mode && typeof mode === "object") {
15506
+ if (mode.getTokenizer)
15507
+ return this.$onChangeMode(mode);
15508
+ var options = mode;
15509
+ var path = options.path;
15510
+ } else {
15511
+ path = mode || "ace/mode/text";
15512
+ }
15513
+ if (!this.$modes["ace/mode/text"])
15514
+ this.$modes["ace/mode/text"] = new TextMode();
15515
+
15516
+ if (this.$modes[path] && !options) {
15517
+ this.$onChangeMode(this.$modes[path]);
15518
+ cb && cb();
15519
+ return;
15520
+ }
15521
+ this.$modeId = path;
15522
+ config.loadModule(["mode", path], function(m) {
15523
+ if (this.$modeId !== path)
15524
+ return cb && cb();
15525
+ if (this.$modes[path] && !options)
15526
+ return this.$onChangeMode(this.$modes[path]);
15527
+ if (m && m.Mode) {
15528
+ m = new m.Mode(options);
15529
+ if (!options) {
15530
+ this.$modes[path] = m;
15531
+ m.$id = path;
15532
+ }
15533
+ this.$onChangeMode(m);
15534
+ cb && cb();
15535
+ }
15536
+ }.bind(this));
15537
+ if (!this.$mode)
15538
+ this.$onChangeMode(this.$modes["ace/mode/text"], true);
15539
+ };
15540
+
15541
+ this.$onChangeMode = function(mode, $isPlaceholder) {
15542
+ if (!$isPlaceholder)
15543
+ this.$modeId = mode.$id;
15544
+ if (this.$mode === mode)
15545
+ return;
15546
+
15547
+ this.$mode = mode;
15548
+
15549
+ this.$stopWorker();
15550
+
15551
+ if (this.$useWorker)
15552
+ this.$startWorker();
15553
+
15554
+ var tokenizer = mode.getTokenizer();
15555
+
15556
+ if(tokenizer.addEventListener !== undefined) {
15557
+ var onReloadTokenizer = this.onReloadTokenizer.bind(this);
15558
+ tokenizer.addEventListener("update", onReloadTokenizer);
15559
+ }
15560
+
15561
+ if (!this.bgTokenizer) {
15562
+ this.bgTokenizer = new BackgroundTokenizer(tokenizer);
15563
+ var _self = this;
15564
+ this.bgTokenizer.addEventListener("update", function(e) {
15565
+ _self._signal("tokenizerUpdate", e);
15566
+ });
15567
+ } else {
15568
+ this.bgTokenizer.setTokenizer(tokenizer);
15569
+ }
15570
+
15571
+ this.bgTokenizer.setDocument(this.getDocument());
15572
+
15573
+ this.tokenRe = mode.tokenRe;
15574
+ this.nonTokenRe = mode.nonTokenRe;
15575
+
15576
+
15577
+ if (!$isPlaceholder) {
15578
+ if (mode.attachToSession)
15579
+ mode.attachToSession(this);
15580
+ this.$options.wrapMethod.set.call(this, this.$wrapMethod);
15581
+ this.$setFolding(mode.foldingRules);
15582
+ this.bgTokenizer.start(0);
15583
+ this._emit("changeMode");
15584
+ }
15585
+ };
15586
+
15587
+ this.$stopWorker = function() {
15588
+ if (this.$worker) {
15589
+ this.$worker.terminate();
15590
+ this.$worker = null;
15591
+ }
15592
+ };
15593
+
15594
+ this.$startWorker = function() {
15595
+ try {
15596
+ this.$worker = this.$mode.createWorker(this);
15597
+ } catch (e) {
15598
+ if (typeof console == "object") {
15599
+ console.log("Could not load worker");
15600
+ console.log(e);
15601
+ }
15602
+ this.$worker = null;
15603
+ }
15604
+ };
15605
+ this.getMode = function() {
15606
+ return this.$mode;
15607
+ };
15608
+
15609
+ this.$scrollTop = 0;
15610
+ this.setScrollTop = function(scrollTop) {
15611
+ if (this.$scrollTop === scrollTop || isNaN(scrollTop))
15612
+ return;
15613
+
15614
+ this.$scrollTop = scrollTop;
15615
+ this._signal("changeScrollTop", scrollTop);
15616
+ };
15617
+ this.getScrollTop = function() {
15618
+ return this.$scrollTop;
15619
+ };
15620
+
15621
+ this.$scrollLeft = 0;
15622
+ this.setScrollLeft = function(scrollLeft) {
15623
+ if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft))
15624
+ return;
15625
+
15626
+ this.$scrollLeft = scrollLeft;
15627
+ this._signal("changeScrollLeft", scrollLeft);
15628
+ };
15629
+ this.getScrollLeft = function() {
15630
+ return this.$scrollLeft;
15631
+ };
15632
+ this.getScreenWidth = function() {
15633
+ this.$computeWidth();
15634
+ if (this.lineWidgets)
15635
+ return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth);
15636
+ return this.screenWidth;
15637
+ };
15638
+
15639
+ this.getLineWidgetMaxWidth = function() {
15640
+ if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth;
15641
+ var width = 0;
15642
+ this.lineWidgets.forEach(function(w) {
15643
+ if (w && w.screenWidth > width)
15644
+ width = w.screenWidth;
15645
+ });
15646
+ return this.lineWidgetWidth = width;
15647
+ };
15648
+
15649
+ this.$computeWidth = function(force) {
15650
+ if (this.$modified || force) {
15651
+ this.$modified = false;
15652
+
15653
+ if (this.$useWrapMode)
15654
+ return this.screenWidth = this.$wrapLimit;
15655
+
15656
+ var lines = this.doc.getAllLines();
15657
+ var cache = this.$rowLengthCache;
15658
+ var longestScreenLine = 0;
15659
+ var foldIndex = 0;
15660
+ var foldLine = this.$foldData[foldIndex];
15661
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
15662
+ var len = lines.length;
15663
+
15664
+ for (var i = 0; i < len; i++) {
15665
+ if (i > foldStart) {
15666
+ i = foldLine.end.row + 1;
15667
+ if (i >= len)
15668
+ break;
15669
+ foldLine = this.$foldData[foldIndex++];
15670
+ foldStart = foldLine ? foldLine.start.row : Infinity;
15671
+ }
15672
+
15673
+ if (cache[i] == null)
15674
+ cache[i] = this.$getStringScreenWidth(lines[i])[0];
15675
+
15676
+ if (cache[i] > longestScreenLine)
15677
+ longestScreenLine = cache[i];
15678
+ }
15679
+ this.screenWidth = longestScreenLine;
15680
+ }
15681
+ };
15682
+ this.getLine = function(row) {
15683
+ return this.doc.getLine(row);
15684
+ };
15685
+ this.getLines = function(firstRow, lastRow) {
15686
+ return this.doc.getLines(firstRow, lastRow);
15687
+ };
15688
+ this.getLength = function() {
15689
+ return this.doc.getLength();
15690
+ };
15691
+ this.getTextRange = function(range) {
15692
+ return this.doc.getTextRange(range || this.selection.getRange());
15693
+ };
15694
+ this.insert = function(position, text) {
15695
+ return this.doc.insert(position, text);
15696
+ };
15697
+ this.remove = function(range) {
15698
+ return this.doc.remove(range);
15699
+ };
15700
+ this.undoChanges = function(deltas, dontSelect) {
15701
+ if (!deltas.length)
15702
+ return;
15703
+
15704
+ this.$fromUndo = true;
15705
+ var lastUndoRange = null;
15706
+ for (var i = deltas.length - 1; i != -1; i--) {
15707
+ var delta = deltas[i];
15708
+ if (delta.group == "doc") {
15709
+ this.doc.revertDeltas(delta.deltas);
15710
+ lastUndoRange =
15711
+ this.$getUndoSelection(delta.deltas, true, lastUndoRange);
15712
+ } else {
15713
+ delta.deltas.forEach(function(foldDelta) {
15714
+ this.addFolds(foldDelta.folds);
15715
+ }, this);
15716
+ }
15717
+ }
15718
+ this.$fromUndo = false;
15719
+ lastUndoRange &&
15720
+ this.$undoSelect &&
15721
+ !dontSelect &&
15722
+ this.selection.setSelectionRange(lastUndoRange);
15723
+ return lastUndoRange;
15724
+ };
15725
+ this.redoChanges = function(deltas, dontSelect) {
15726
+ if (!deltas.length)
15727
+ return;
15728
+
15729
+ this.$fromUndo = true;
15730
+ var lastUndoRange = null;
15731
+ for (var i = 0; i < deltas.length; i++) {
15732
+ var delta = deltas[i];
15733
+ if (delta.group == "doc") {
15734
+ this.doc.applyDeltas(delta.deltas);
15735
+ lastUndoRange =
15736
+ this.$getUndoSelection(delta.deltas, false, lastUndoRange);
15737
+ }
15738
+ }
15739
+ this.$fromUndo = false;
15740
+ lastUndoRange &&
15741
+ this.$undoSelect &&
15742
+ !dontSelect &&
15743
+ this.selection.setSelectionRange(lastUndoRange);
15744
+ return lastUndoRange;
15745
+ };
15746
+ this.setUndoSelect = function(enable) {
15747
+ this.$undoSelect = enable;
15748
+ };
15749
+
15750
+ this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
15751
+ function isInsert(delta) {
15752
+ var insert =
15753
+ delta.action === "insertText" || delta.action === "insertLines";
15754
+ return isUndo ? !insert : insert;
15755
+ }
15756
+
15757
+ var delta = deltas[0];
15758
+ var range, point;
15759
+ var lastDeltaIsInsert = false;
15760
+ if (isInsert(delta)) {
15761
+ range = Range.fromPoints(delta.range.start, delta.range.end);
15762
+ lastDeltaIsInsert = true;
15763
+ } else {
15764
+ range = Range.fromPoints(delta.range.start, delta.range.start);
15765
+ lastDeltaIsInsert = false;
15766
+ }
15767
+
15768
+ for (var i = 1; i < deltas.length; i++) {
15769
+ delta = deltas[i];
15770
+ if (isInsert(delta)) {
15771
+ point = delta.range.start;
15772
+ if (range.compare(point.row, point.column) == -1) {
15773
+ range.setStart(delta.range.start);
15774
+ }
15775
+ point = delta.range.end;
15776
+ if (range.compare(point.row, point.column) == 1) {
15777
+ range.setEnd(delta.range.end);
15778
+ }
15779
+ lastDeltaIsInsert = true;
15780
+ } else {
15781
+ point = delta.range.start;
15782
+ if (range.compare(point.row, point.column) == -1) {
15783
+ range =
15784
+ Range.fromPoints(delta.range.start, delta.range.start);
15785
+ }
15786
+ lastDeltaIsInsert = false;
15787
+ }
15788
+ }
15789
+ if (lastUndoRange != null) {
15790
+ if (Range.comparePoints(lastUndoRange.start, range.start) === 0) {
15791
+ lastUndoRange.start.column += range.end.column - range.start.column;
15792
+ lastUndoRange.end.column += range.end.column - range.start.column;
15793
+ }
15794
+
15795
+ var cmp = lastUndoRange.compareRange(range);
15796
+ if (cmp == 1) {
15797
+ range.setStart(lastUndoRange.start);
15798
+ } else if (cmp == -1) {
15799
+ range.setEnd(lastUndoRange.end);
15800
+ }
15801
+ }
15802
+
15803
+ return range;
15804
+ };
15805
+ this.replace = function(range, text) {
15806
+ return this.doc.replace(range, text);
15807
+ };
15808
+ this.moveText = function(fromRange, toPosition, copy) {
15809
+ var text = this.getTextRange(fromRange);
15810
+ var folds = this.getFoldsInRange(fromRange);
15811
+
15812
+ var toRange = Range.fromPoints(toPosition, toPosition);
15813
+ if (!copy) {
15814
+ this.remove(fromRange);
15815
+ var rowDiff = fromRange.start.row - fromRange.end.row;
15816
+ var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column;
15817
+ if (collDiff) {
15818
+ if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column)
15819
+ toRange.start.column += collDiff;
15820
+ if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column)
15821
+ toRange.end.column += collDiff;
15822
+ }
15823
+ if (rowDiff && toRange.start.row >= fromRange.end.row) {
15824
+ toRange.start.row += rowDiff;
15825
+ toRange.end.row += rowDiff;
15826
+ }
15827
+ }
15828
+
15829
+ toRange.end = this.insert(toRange.start, text);
15830
+ if (folds.length) {
15831
+ var oldStart = fromRange.start;
15832
+ var newStart = toRange.start;
15833
+ var rowDiff = newStart.row - oldStart.row;
15834
+ var collDiff = newStart.column - oldStart.column;
15835
+ this.addFolds(folds.map(function(x) {
15836
+ x = x.clone();
15837
+ if (x.start.row == oldStart.row)
15838
+ x.start.column += collDiff;
15839
+ if (x.end.row == oldStart.row)
15840
+ x.end.column += collDiff;
15841
+ x.start.row += rowDiff;
15842
+ x.end.row += rowDiff;
15843
+ return x;
15844
+ }));
15845
+ }
15846
+
15847
+ return toRange;
15848
+ };
15849
+ this.indentRows = function(startRow, endRow, indentString) {
15850
+ indentString = indentString.replace(/\t/g, this.getTabString());
15851
+ for (var row=startRow; row<=endRow; row++)
15852
+ this.insert({row: row, column:0}, indentString);
15853
+ };
15854
+ this.outdentRows = function (range) {
15855
+ var rowRange = range.collapseRows();
15856
+ var deleteRange = new Range(0, 0, 0, 0);
15857
+ var size = this.getTabSize();
15858
+
15859
+ for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
15860
+ var line = this.getLine(i);
15861
+
15862
+ deleteRange.start.row = i;
15863
+ deleteRange.end.row = i;
15864
+ for (var j = 0; j < size; ++j)
15865
+ if (line.charAt(j) != ' ')
15866
+ break;
15867
+ if (j < size && line.charAt(j) == '\t') {
15868
+ deleteRange.start.column = j;
15869
+ deleteRange.end.column = j + 1;
15870
+ } else {
15871
+ deleteRange.start.column = 0;
15872
+ deleteRange.end.column = j;
15873
+ }
15874
+ this.remove(deleteRange);
15875
+ }
15876
+ };
15877
+
15878
+ this.$moveLines = function(firstRow, lastRow, dir) {
15879
+ firstRow = this.getRowFoldStart(firstRow);
15880
+ lastRow = this.getRowFoldEnd(lastRow);
15881
+ if (dir < 0) {
15882
+ var row = this.getRowFoldStart(firstRow + dir);
15883
+ if (row < 0) return 0;
15884
+ var diff = row-firstRow;
15885
+ } else if (dir > 0) {
15886
+ var row = this.getRowFoldEnd(lastRow + dir);
15887
+ if (row > this.doc.getLength()-1) return 0;
15888
+ var diff = row-lastRow;
15889
+ } else {
15890
+ firstRow = this.$clipRowToDocument(firstRow);
15891
+ lastRow = this.$clipRowToDocument(lastRow);
15892
+ var diff = lastRow - firstRow + 1;
15893
+ }
15894
+
15895
+ var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);
15896
+ var folds = this.getFoldsInRange(range).map(function(x){
15897
+ x = x.clone();
15898
+ x.start.row += diff;
15899
+ x.end.row += diff;
15900
+ return x;
15901
+ });
15902
+
15903
+ var lines = dir == 0
15904
+ ? this.doc.getLines(firstRow, lastRow)
15905
+ : this.doc.removeLines(firstRow, lastRow);
15906
+ this.doc.insertLines(firstRow+diff, lines);
15907
+ folds.length && this.addFolds(folds);
15908
+ return diff;
15909
+ };
15910
+ this.moveLinesUp = function(firstRow, lastRow) {
15911
+ return this.$moveLines(firstRow, lastRow, -1);
15912
+ };
15913
+ this.moveLinesDown = function(firstRow, lastRow) {
15914
+ return this.$moveLines(firstRow, lastRow, 1);
15915
+ };
15916
+ this.duplicateLines = function(firstRow, lastRow) {
15917
+ return this.$moveLines(firstRow, lastRow, 0);
15918
+ };
15919
+
15920
+
15921
+ this.$clipRowToDocument = function(row) {
15922
+ return Math.max(0, Math.min(row, this.doc.getLength()-1));
15923
+ };
15924
+
15925
+ this.$clipColumnToRow = function(row, column) {
15926
+ if (column < 0)
15927
+ return 0;
15928
+ return Math.min(this.doc.getLine(row).length, column);
15929
+ };
15930
+
15931
+
15932
+ this.$clipPositionToDocument = function(row, column) {
15933
+ column = Math.max(0, column);
15934
+
15935
+ if (row < 0) {
15936
+ row = 0;
15937
+ column = 0;
15938
+ } else {
15939
+ var len = this.doc.getLength();
15940
+ if (row >= len) {
15941
+ row = len - 1;
15942
+ column = this.doc.getLine(len-1).length;
15943
+ } else {
15944
+ column = Math.min(this.doc.getLine(row).length, column);
15945
+ }
15946
+ }
15947
+
15948
+ return {
15949
+ row: row,
15950
+ column: column
15951
+ };
15952
+ };
15953
+
15954
+ this.$clipRangeToDocument = function(range) {
15955
+ if (range.start.row < 0) {
15956
+ range.start.row = 0;
15957
+ range.start.column = 0;
15958
+ } else {
15959
+ range.start.column = this.$clipColumnToRow(
15960
+ range.start.row,
15961
+ range.start.column
15962
+ );
15963
+ }
15964
+
15965
+ var len = this.doc.getLength() - 1;
15966
+ if (range.end.row > len) {
15967
+ range.end.row = len;
15968
+ range.end.column = this.doc.getLine(len).length;
15969
+ } else {
15970
+ range.end.column = this.$clipColumnToRow(
15971
+ range.end.row,
15972
+ range.end.column
15973
+ );
15974
+ }
15975
+ return range;
15976
+ };
15977
+ this.$wrapLimit = 80;
15978
+ this.$useWrapMode = false;
15979
+ this.$wrapLimitRange = {
15980
+ min : null,
15981
+ max : null
15982
+ };
15983
+ this.setUseWrapMode = function(useWrapMode) {
15984
+ if (useWrapMode != this.$useWrapMode) {
15985
+ this.$useWrapMode = useWrapMode;
15986
+ this.$modified = true;
15987
+ this.$resetRowCache(0);
15988
+ if (useWrapMode) {
15989
+ var len = this.getLength();
15990
+ this.$wrapData = Array(len);
15991
+ this.$updateWrapData(0, len - 1);
15992
+ }
15993
+
15994
+ this._signal("changeWrapMode");
15995
+ }
15996
+ };
15997
+ this.getUseWrapMode = function() {
15998
+ return this.$useWrapMode;
15999
+ };
16000
+ this.setWrapLimitRange = function(min, max) {
16001
+ if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
16002
+ this.$wrapLimitRange = {
16003
+ min: min,
16004
+ max: max
16005
+ };
16006
+ this.$modified = true;
16007
+ this._signal("changeWrapMode");
16008
+ }
16009
+ };
16010
+ this.adjustWrapLimit = function(desiredLimit, $printMargin) {
16011
+ var limits = this.$wrapLimitRange;
16012
+ if (limits.max < 0)
16013
+ limits = {min: $printMargin, max: $printMargin};
16014
+ var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max);
16015
+ if (wrapLimit != this.$wrapLimit && wrapLimit > 1) {
16016
+ this.$wrapLimit = wrapLimit;
16017
+ this.$modified = true;
16018
+ if (this.$useWrapMode) {
16019
+ this.$updateWrapData(0, this.getLength() - 1);
16020
+ this.$resetRowCache(0);
16021
+ this._signal("changeWrapLimit");
16022
+ }
16023
+ return true;
16024
+ }
16025
+ return false;
16026
+ };
16027
+
16028
+ this.$constrainWrapLimit = function(wrapLimit, min, max) {
16029
+ if (min)
16030
+ wrapLimit = Math.max(min, wrapLimit);
16031
+
16032
+ if (max)
16033
+ wrapLimit = Math.min(max, wrapLimit);
16034
+
16035
+ return wrapLimit;
16036
+ };
16037
+ this.getWrapLimit = function() {
16038
+ return this.$wrapLimit;
16039
+ };
16040
+ this.setWrapLimit = function (limit) {
16041
+ this.setWrapLimitRange(limit, limit);
16042
+ };
16043
+ this.getWrapLimitRange = function() {
16044
+ return {
16045
+ min : this.$wrapLimitRange.min,
16046
+ max : this.$wrapLimitRange.max
16047
+ };
16048
+ };
16049
+
16050
+ this.$updateInternalDataOnChange = function(e) {
16051
+ var useWrapMode = this.$useWrapMode;
16052
+ var len;
16053
+ var action = e.data.action;
16054
+ var firstRow = e.data.range.start.row;
16055
+ var lastRow = e.data.range.end.row;
16056
+ var start = e.data.range.start;
16057
+ var end = e.data.range.end;
16058
+ var removedFolds = null;
16059
+
16060
+ if (action.indexOf("Lines") != -1) {
16061
+ if (action == "insertLines") {
16062
+ lastRow = firstRow + (e.data.lines.length);
16063
+ } else {
16064
+ lastRow = firstRow;
16065
+ }
16066
+ len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
16067
+ } else {
16068
+ len = lastRow - firstRow;
16069
+ }
16070
+
16071
+ this.$updating = true;
16072
+ if (len != 0) {
16073
+ if (action.indexOf("remove") != -1) {
16074
+ this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
16075
+
16076
+ var foldLines = this.$foldData;
16077
+ removedFolds = this.getFoldsInRange(e.data.range);
16078
+ this.removeFolds(removedFolds);
16079
+
16080
+ var foldLine = this.getFoldLine(end.row);
16081
+ var idx = 0;
16082
+ if (foldLine) {
16083
+ foldLine.addRemoveChars(end.row, end.column, start.column - end.column);
16084
+ foldLine.shiftRow(-len);
16085
+
16086
+ var foldLineBefore = this.getFoldLine(firstRow);
16087
+ if (foldLineBefore && foldLineBefore !== foldLine) {
16088
+ foldLineBefore.merge(foldLine);
16089
+ foldLine = foldLineBefore;
16090
+ }
16091
+ idx = foldLines.indexOf(foldLine) + 1;
16092
+ }
16093
+
16094
+ for (idx; idx < foldLines.length; idx++) {
16095
+ var foldLine = foldLines[idx];
16096
+ if (foldLine.start.row >= end.row) {
16097
+ foldLine.shiftRow(-len);
16098
+ }
16099
+ }
16100
+
16101
+ lastRow = firstRow;
16102
+ } else {
16103
+ var args = Array(len);
16104
+ args.unshift(firstRow, 0);
16105
+ var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache
16106
+ arr.splice.apply(arr, args);
16107
+ var foldLines = this.$foldData;
16108
+ var foldLine = this.getFoldLine(firstRow);
16109
+ var idx = 0;
16110
+ if (foldLine) {
16111
+ var cmp = foldLine.range.compareInside(start.row, start.column);
16112
+ if (cmp == 0) {
16113
+ foldLine = foldLine.split(start.row, start.column);
16114
+ if (foldLine) {
16115
+ foldLine.shiftRow(len);
16116
+ foldLine.addRemoveChars(lastRow, 0, end.column - start.column);
16117
+ }
16118
+ } else
16119
+ if (cmp == -1) {
16120
+ foldLine.addRemoveChars(firstRow, 0, end.column - start.column);
16121
+ foldLine.shiftRow(len);
16122
+ }
16123
+ idx = foldLines.indexOf(foldLine) + 1;
16124
+ }
16125
+
16126
+ for (idx; idx < foldLines.length; idx++) {
16127
+ var foldLine = foldLines[idx];
16128
+ if (foldLine.start.row >= firstRow) {
16129
+ foldLine.shiftRow(len);
16130
+ }
16131
+ }
16132
+ }
16133
+ } else {
16134
+ len = Math.abs(e.data.range.start.column - e.data.range.end.column);
16135
+ if (action.indexOf("remove") != -1) {
16136
+ removedFolds = this.getFoldsInRange(e.data.range);
16137
+ this.removeFolds(removedFolds);
16138
+
16139
+ len = -len;
16140
+ }
16141
+ var foldLine = this.getFoldLine(firstRow);
16142
+ if (foldLine) {
16143
+ foldLine.addRemoveChars(firstRow, start.column, len);
16144
+ }
16145
+ }
16146
+
16147
+ if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
16148
+ console.error("doc.getLength() and $wrapData.length have to be the same!");
16149
+ }
16150
+ this.$updating = false;
16151
+
16152
+ if (useWrapMode)
16153
+ this.$updateWrapData(firstRow, lastRow);
16154
+ else
16155
+ this.$updateRowLengthCache(firstRow, lastRow);
16156
+
16157
+ return removedFolds;
16158
+ };
16159
+
16160
+ this.$updateRowLengthCache = function(firstRow, lastRow, b) {
16161
+ this.$rowLengthCache[firstRow] = null;
16162
+ this.$rowLengthCache[lastRow] = null;
16163
+ };
16164
+
16165
+ this.$updateWrapData = function(firstRow, lastRow) {
16166
+ var lines = this.doc.getAllLines();
16167
+ var tabSize = this.getTabSize();
16168
+ var wrapData = this.$wrapData;
16169
+ var wrapLimit = this.$wrapLimit;
16170
+ var tokens;
16171
+ var foldLine;
16172
+
16173
+ var row = firstRow;
16174
+ lastRow = Math.min(lastRow, lines.length - 1);
16175
+ while (row <= lastRow) {
16176
+ foldLine = this.getFoldLine(row, foldLine);
16177
+ if (!foldLine) {
16178
+ tokens = this.$getDisplayTokens(lines[row]);
16179
+ wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
16180
+ row ++;
16181
+ } else {
16182
+ tokens = [];
16183
+ foldLine.walk(function(placeholder, row, column, lastColumn) {
16184
+ var walkTokens;
16185
+ if (placeholder != null) {
16186
+ walkTokens = this.$getDisplayTokens(
16187
+ placeholder, tokens.length);
16188
+ walkTokens[0] = PLACEHOLDER_START;
16189
+ for (var i = 1; i < walkTokens.length; i++) {
16190
+ walkTokens[i] = PLACEHOLDER_BODY;
16191
+ }
16192
+ } else {
16193
+ walkTokens = this.$getDisplayTokens(
16194
+ lines[row].substring(lastColumn, column),
16195
+ tokens.length);
16196
+ }
16197
+ tokens = tokens.concat(walkTokens);
16198
+ }.bind(this),
16199
+ foldLine.end.row,
16200
+ lines[foldLine.end.row].length + 1
16201
+ );
16202
+
16203
+ wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
16204
+ row = foldLine.end.row + 1;
16205
+ }
16206
+ }
16207
+ };
16208
+ var CHAR = 1,
16209
+ CHAR_EXT = 2,
16210
+ PLACEHOLDER_START = 3,
16211
+ PLACEHOLDER_BODY = 4,
16212
+ PUNCTUATION = 9,
16213
+ SPACE = 10,
16214
+ TAB = 11,
16215
+ TAB_SPACE = 12;
16216
+
16217
+
16218
+ this.$computeWrapSplits = function(tokens, wrapLimit) {
16219
+ if (tokens.length == 0) {
16220
+ return [];
16221
+ }
16222
+
16223
+ var splits = [];
16224
+ var displayLength = tokens.length;
16225
+ var lastSplit = 0, lastDocSplit = 0;
16226
+
16227
+ var isCode = this.$wrapAsCode;
16228
+
16229
+ function addSplit(screenPos) {
16230
+ var displayed = tokens.slice(lastSplit, screenPos);
16231
+ var len = displayed.length;
16232
+ displayed.join("").
16233
+ replace(/12/g, function() {
16234
+ len -= 1;
16235
+ }).
16236
+ replace(/2/g, function() {
16237
+ len -= 1;
16238
+ });
16239
+
16240
+ lastDocSplit += len;
16241
+ splits.push(lastDocSplit);
16242
+ lastSplit = screenPos;
16243
+ }
16244
+
16245
+ while (displayLength - lastSplit > wrapLimit) {
16246
+ var split = lastSplit + wrapLimit;
16247
+ if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {
16248
+ addSplit(split);
16249
+ continue;
16250
+ }
16251
+ if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) {
16252
+ for (split; split != lastSplit - 1; split--) {
16253
+ if (tokens[split] == PLACEHOLDER_START) {
16254
+ break;
16255
+ }
16256
+ }
16257
+ if (split > lastSplit) {
16258
+ addSplit(split);
16259
+ continue;
16260
+ }
16261
+ split = lastSplit + wrapLimit;
16262
+ for (split; split < tokens.length; split++) {
16263
+ if (tokens[split] != PLACEHOLDER_BODY) {
16264
+ break;
16265
+ }
16266
+ }
16267
+ if (split == tokens.length) {
16268
+ break; // Breaks the while-loop.
16269
+ }
16270
+ addSplit(split);
16271
+ continue;
16272
+ }
16273
+ var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1);
16274
+ while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
16275
+ split --;
16276
+ }
16277
+ if (isCode) {
16278
+ while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
16279
+ split --;
16280
+ }
16281
+ while (split > minSplit && tokens[split] == PUNCTUATION) {
16282
+ split --;
16283
+ }
16284
+ } else {
16285
+ while (split > minSplit && tokens[split] < SPACE) {
16286
+ split --;
16287
+ }
16288
+ }
16289
+ if (split > minSplit) {
16290
+ addSplit(++split);
16291
+ continue;
16292
+ }
16293
+ split = lastSplit + wrapLimit;
16294
+ if (tokens[split] == CHAR_EXT)
16295
+ split--;
16296
+ addSplit(split);
16297
+ }
16298
+ return splits;
16299
+ };
16300
+ this.$getDisplayTokens = function(str, offset) {
16301
+ var arr = [];
16302
+ var tabSize;
16303
+ offset = offset || 0;
16304
+
16305
+ for (var i = 0; i < str.length; i++) {
16306
+ var c = str.charCodeAt(i);
16307
+ if (c == 9) {
16308
+ tabSize = this.getScreenTabSize(arr.length + offset);
16309
+ arr.push(TAB);
16310
+ for (var n = 1; n < tabSize; n++) {
16311
+ arr.push(TAB_SPACE);
16312
+ }
16313
+ }
16314
+ else if (c == 32) {
16315
+ arr.push(SPACE);
16316
+ } else if((c > 39 && c < 48) || (c > 57 && c < 64)) {
16317
+ arr.push(PUNCTUATION);
16318
+ }
16319
+ else if (c >= 0x1100 && isFullWidth(c)) {
16320
+ arr.push(CHAR, CHAR_EXT);
16321
+ } else {
16322
+ arr.push(CHAR);
16323
+ }
16324
+ }
16325
+ return arr;
16326
+ };
16327
+ this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
16328
+ if (maxScreenColumn == 0)
16329
+ return [0, 0];
16330
+ if (maxScreenColumn == null)
16331
+ maxScreenColumn = Infinity;
16332
+ screenColumn = screenColumn || 0;
16333
+
16334
+ var c, column;
16335
+ for (column = 0; column < str.length; column++) {
16336
+ c = str.charCodeAt(column);
16337
+ if (c == 9) {
16338
+ screenColumn += this.getScreenTabSize(screenColumn);
16339
+ }
16340
+ else if (c >= 0x1100 && isFullWidth(c)) {
16341
+ screenColumn += 2;
16342
+ } else {
16343
+ screenColumn += 1;
16344
+ }
16345
+ if (screenColumn > maxScreenColumn) {
16346
+ break;
16347
+ }
16348
+ }
16349
+
16350
+ return [screenColumn, column];
16351
+ };
16352
+
16353
+ this.lineWidgets = null;
16354
+ this.getRowLength = function(row) {
16355
+ if (this.lineWidgets)
16356
+ var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;
16357
+ else
16358
+ h = 0
16359
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
16360
+ return 1 + h;
16361
+ } else {
16362
+ return this.$wrapData[row].length + 1 + h;
16363
+ }
16364
+ };
16365
+ this.getRowLineCount = function(row) {
16366
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
16367
+ return 1;
16368
+ } else {
16369
+ return this.$wrapData[row].length + 1;
16370
+ }
16371
+ };
16372
+ this.getScreenLastRowColumn = function(screenRow) {
16373
+ var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
16374
+ return this.documentToScreenColumn(pos.row, pos.column);
16375
+ };
16376
+ this.getDocumentLastRowColumn = function(docRow, docColumn) {
16377
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
16378
+ return this.getScreenLastRowColumn(screenRow);
16379
+ };
16380
+ this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
16381
+ var screenRow = this.documentToScreenRow(docRow, docColumn);
16382
+ return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
16383
+ };
16384
+ this.getRowSplitData = function(row) {
16385
+ if (!this.$useWrapMode) {
16386
+ return undefined;
16387
+ } else {
16388
+ return this.$wrapData[row];
16389
+ }
16390
+ };
16391
+ this.getScreenTabSize = function(screenColumn) {
16392
+ return this.$tabSize - screenColumn % this.$tabSize;
16393
+ };
16394
+
16395
+
16396
+ this.screenToDocumentRow = function(screenRow, screenColumn) {
16397
+ return this.screenToDocumentPosition(screenRow, screenColumn).row;
16398
+ };
16399
+
16400
+
16401
+ this.screenToDocumentColumn = function(screenRow, screenColumn) {
16402
+ return this.screenToDocumentPosition(screenRow, screenColumn).column;
16403
+ };
16404
+ this.screenToDocumentPosition = function(screenRow, screenColumn) {
16405
+ if (screenRow < 0)
16406
+ return {row: 0, column: 0};
16407
+
16408
+ var line;
16409
+ var docRow = 0;
16410
+ var docColumn = 0;
16411
+ var column;
16412
+ var row = 0;
16413
+ var rowLength = 0;
16414
+
16415
+ var rowCache = this.$screenRowCache;
16416
+ var i = this.$getRowCacheIndex(rowCache, screenRow);
16417
+ var l = rowCache.length;
16418
+ if (l && i >= 0) {
16419
+ var row = rowCache[i];
16420
+ var docRow = this.$docRowCache[i];
16421
+ var doCache = screenRow > rowCache[l - 1];
16422
+ } else {
16423
+ var doCache = !l;
16424
+ }
16425
+
16426
+ var maxRow = this.getLength() - 1;
16427
+ var foldLine = this.getNextFoldLine(docRow);
16428
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
16429
+
16430
+ while (row <= screenRow) {
16431
+ rowLength = this.getRowLength(docRow);
16432
+ if (row + rowLength > screenRow || docRow >= maxRow) {
16433
+ break;
16434
+ } else {
16435
+ row += rowLength;
16436
+ docRow++;
16437
+ if (docRow > foldStart) {
16438
+ docRow = foldLine.end.row+1;
16439
+ foldLine = this.getNextFoldLine(docRow, foldLine);
16440
+ foldStart = foldLine ? foldLine.start.row : Infinity;
16441
+ }
16442
+ }
16443
+
16444
+ if (doCache) {
16445
+ this.$docRowCache.push(docRow);
16446
+ this.$screenRowCache.push(row);
16447
+ }
16448
+ }
16449
+
16450
+ if (foldLine && foldLine.start.row <= docRow) {
16451
+ line = this.getFoldDisplayLine(foldLine);
16452
+ docRow = foldLine.start.row;
16453
+ } else if (row + rowLength <= screenRow || docRow > maxRow) {
16454
+ return {
16455
+ row: maxRow,
16456
+ column: this.getLine(maxRow).length
16457
+ };
16458
+ } else {
16459
+ line = this.getLine(docRow);
16460
+ foldLine = null;
16461
+ }
16462
+
16463
+ if (this.$useWrapMode) {
16464
+ var splits = this.$wrapData[docRow];
16465
+ if (splits) {
16466
+ var splitIndex = Math.floor(screenRow - row);
16467
+ column = splits[splitIndex];
16468
+ if(splitIndex > 0 && splits.length) {
16469
+ docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
16470
+ line = line.substring(docColumn);
16471
+ }
16472
+ }
16473
+ }
16474
+
16475
+ docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
16476
+ if (this.$useWrapMode && docColumn >= column)
16477
+ docColumn = column - 1;
16478
+
16479
+ if (foldLine)
16480
+ return foldLine.idxToPosition(docColumn);
16481
+
16482
+ return {row: docRow, column: docColumn};
16483
+ };
16484
+ this.documentToScreenPosition = function(docRow, docColumn) {
16485
+ if (typeof docColumn === "undefined")
16486
+ var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
16487
+ else
16488
+ pos = this.$clipPositionToDocument(docRow, docColumn);
16489
+
16490
+ docRow = pos.row;
16491
+ docColumn = pos.column;
16492
+
16493
+ var screenRow = 0;
16494
+ var foldStartRow = null;
16495
+ var fold = null;
16496
+ fold = this.getFoldAt(docRow, docColumn, 1);
16497
+ if (fold) {
16498
+ docRow = fold.start.row;
16499
+ docColumn = fold.start.column;
16500
+ }
16501
+
16502
+ var rowEnd, row = 0;
16503
+
16504
+
16505
+ var rowCache = this.$docRowCache;
16506
+ var i = this.$getRowCacheIndex(rowCache, docRow);
16507
+ var l = rowCache.length;
16508
+ if (l && i >= 0) {
16509
+ var row = rowCache[i];
16510
+ var screenRow = this.$screenRowCache[i];
16511
+ var doCache = docRow > rowCache[l - 1];
16512
+ } else {
16513
+ var doCache = !l;
16514
+ }
16515
+
16516
+ var foldLine = this.getNextFoldLine(row);
16517
+ var foldStart = foldLine ?foldLine.start.row :Infinity;
16518
+
16519
+ while (row < docRow) {
16520
+ if (row >= foldStart) {
16521
+ rowEnd = foldLine.end.row + 1;
16522
+ if (rowEnd > docRow)
16523
+ break;
16524
+ foldLine = this.getNextFoldLine(rowEnd, foldLine);
16525
+ foldStart = foldLine ?foldLine.start.row :Infinity;
16526
+ }
16527
+ else {
16528
+ rowEnd = row + 1;
16529
+ }
16530
+
16531
+ screenRow += this.getRowLength(row);
16532
+ row = rowEnd;
16533
+
16534
+ if (doCache) {
16535
+ this.$docRowCache.push(row);
16536
+ this.$screenRowCache.push(screenRow);
16537
+ }
16538
+ }
16539
+ var textLine = "";
16540
+ if (foldLine && row >= foldStart) {
16541
+ textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
16542
+ foldStartRow = foldLine.start.row;
16543
+ } else {
16544
+ textLine = this.getLine(docRow).substring(0, docColumn);
16545
+ foldStartRow = docRow;
16546
+ }
16547
+ if (this.$useWrapMode) {
16548
+ var wrapRow = this.$wrapData[foldStartRow];
16549
+ if (wrapRow) {
16550
+ var screenRowOffset = 0;
16551
+ while (textLine.length >= wrapRow[screenRowOffset]) {
16552
+ screenRow ++;
16553
+ screenRowOffset++;
16554
+ }
16555
+ textLine = textLine.substring(
16556
+ wrapRow[screenRowOffset - 1] || 0, textLine.length
16557
+ );
16558
+ }
16559
+ }
16560
+
16561
+ return {
16562
+ row: screenRow,
16563
+ column: this.$getStringScreenWidth(textLine)[0]
16564
+ };
16565
+ };
16566
+ this.documentToScreenColumn = function(row, docColumn) {
16567
+ return this.documentToScreenPosition(row, docColumn).column;
16568
+ };
16569
+ this.documentToScreenRow = function(docRow, docColumn) {
16570
+ return this.documentToScreenPosition(docRow, docColumn).row;
16571
+ };
16572
+ this.getScreenLength = function() {
16573
+ var screenRows = 0;
16574
+ var fold = null;
16575
+ if (!this.$useWrapMode) {
16576
+ screenRows = this.getLength();
16577
+ var foldData = this.$foldData;
16578
+ for (var i = 0; i < foldData.length; i++) {
16579
+ fold = foldData[i];
16580
+ screenRows -= fold.end.row - fold.start.row;
16581
+ }
16582
+ } else {
16583
+ var lastRow = this.$wrapData.length;
16584
+ var row = 0, i = 0;
16585
+ var fold = this.$foldData[i++];
16586
+ var foldStart = fold ? fold.start.row :Infinity;
16587
+
16588
+ while (row < lastRow) {
16589
+ var splits = this.$wrapData[row];
16590
+ screenRows += splits ? splits.length + 1 : 1;
16591
+ row ++;
16592
+ if (row > foldStart) {
16593
+ row = fold.end.row+1;
16594
+ fold = this.$foldData[i++];
16595
+ foldStart = fold ?fold.start.row :Infinity;
16596
+ }
16597
+ }
16598
+ }
16599
+ if (this.lineWidgets)
16600
+ screenRows += this.$getWidgetScreenLength();
16601
+
16602
+ return screenRows;
16603
+ };
16604
+ this.$setFontMetrics = function(fm) {
16605
+ };
16606
+
16607
+ this.destroy = function() {
16608
+ if (this.bgTokenizer) {
16609
+ this.bgTokenizer.setDocument(null);
16610
+ this.bgTokenizer = null;
16611
+ }
16612
+ this.$stopWorker();
16613
+ };
16614
+ function isFullWidth(c) {
16615
+ if (c < 0x1100)
16616
+ return false;
16617
+ return c >= 0x1100 && c <= 0x115F ||
16618
+ c >= 0x11A3 && c <= 0x11A7 ||
16619
+ c >= 0x11FA && c <= 0x11FF ||
16620
+ c >= 0x2329 && c <= 0x232A ||
16621
+ c >= 0x2E80 && c <= 0x2E99 ||
16622
+ c >= 0x2E9B && c <= 0x2EF3 ||
16623
+ c >= 0x2F00 && c <= 0x2FD5 ||
16624
+ c >= 0x2FF0 && c <= 0x2FFB ||
16625
+ c >= 0x3000 && c <= 0x303E ||
16626
+ c >= 0x3041 && c <= 0x3096 ||
16627
+ c >= 0x3099 && c <= 0x30FF ||
16628
+ c >= 0x3105 && c <= 0x312D ||
16629
+ c >= 0x3131 && c <= 0x318E ||
16630
+ c >= 0x3190 && c <= 0x31BA ||
16631
+ c >= 0x31C0 && c <= 0x31E3 ||
16632
+ c >= 0x31F0 && c <= 0x321E ||
16633
+ c >= 0x3220 && c <= 0x3247 ||
16634
+ c >= 0x3250 && c <= 0x32FE ||
16635
+ c >= 0x3300 && c <= 0x4DBF ||
16636
+ c >= 0x4E00 && c <= 0xA48C ||
16637
+ c >= 0xA490 && c <= 0xA4C6 ||
16638
+ c >= 0xA960 && c <= 0xA97C ||
16639
+ c >= 0xAC00 && c <= 0xD7A3 ||
16640
+ c >= 0xD7B0 && c <= 0xD7C6 ||
16641
+ c >= 0xD7CB && c <= 0xD7FB ||
16642
+ c >= 0xF900 && c <= 0xFAFF ||
16643
+ c >= 0xFE10 && c <= 0xFE19 ||
16644
+ c >= 0xFE30 && c <= 0xFE52 ||
16645
+ c >= 0xFE54 && c <= 0xFE66 ||
16646
+ c >= 0xFE68 && c <= 0xFE6B ||
16647
+ c >= 0xFF01 && c <= 0xFF60 ||
16648
+ c >= 0xFFE0 && c <= 0xFFE6;
16649
+ };
16650
+
16651
+ }).call(EditSession.prototype);
16652
+
16653
+ acequire("./edit_session/folding").Folding.call(EditSession.prototype);
16654
+ acequire("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype);
16655
+
16656
+
16657
+ config.defineOptions(EditSession.prototype, "session", {
16658
+ wrap: {
16659
+ set: function(value) {
16660
+ if (!value || value == "off")
16661
+ value = false;
16662
+ else if (value == "free")
16663
+ value = true;
16664
+ else if (value == "printMargin")
16665
+ value = -1;
16666
+ else if (typeof value == "string")
16667
+ value = parseInt(value, 10) || false;
16668
+
16669
+ if (this.$wrap == value)
16670
+ return;
16671
+ if (!value) {
16672
+ this.setUseWrapMode(false);
16673
+ } else {
16674
+ var col = typeof value == "number" ? value : null;
16675
+ this.setWrapLimitRange(col, col);
16676
+ this.setUseWrapMode(true);
16677
+ }
16678
+ this.$wrap = value;
16679
+ },
16680
+ get: function() {
16681
+ if (this.getUseWrapMode()) {
16682
+ if (this.$wrap == -1)
16683
+ return "printMargin";
16684
+ if (!this.getWrapLimitRange().min)
16685
+ return "free";
16686
+ return this.$wrap;
16687
+ }
16688
+ return "off";
16689
+ },
16690
+ handlesSet: true
16691
+ },
16692
+ wrapMethod: {
16693
+ set: function(val) {
16694
+ val = val == "auto"
16695
+ ? this.$mode.type != "text"
16696
+ : val != "text";
16697
+ if (val != this.$wrapAsCode) {
16698
+ this.$wrapAsCode = val;
16699
+ if (this.$useWrapMode) {
16700
+ this.$modified = true;
16701
+ this.$resetRowCache(0);
16702
+ this.$updateWrapData(0, this.getLength() - 1);
16703
+ }
16704
+ }
16705
+ },
16706
+ initialValue: "auto"
16707
+ },
16708
+ firstLineNumber: {
16709
+ set: function() {this._signal("changeBreakpoint");},
16710
+ initialValue: 1
16711
+ },
16712
+ useWorker: {
16713
+ set: function(useWorker) {
16714
+ this.$useWorker = useWorker;
16715
+
16716
+ this.$stopWorker();
16717
+ if (useWorker)
16718
+ this.$startWorker();
16719
+ },
16720
+ initialValue: true
16721
+ },
16722
+ useSoftTabs: {initialValue: true},
16723
+ tabSize: {
16724
+ set: function(tabSize) {
16725
+ if (isNaN(tabSize) || this.$tabSize === tabSize) return;
16726
+
16727
+ this.$modified = true;
16728
+ this.$rowLengthCache = [];
16729
+ this.$tabSize = tabSize;
16730
+ this._signal("changeTabSize");
16731
+ },
16732
+ initialValue: 4,
16733
+ handlesSet: true
16734
+ },
16735
+ overwrite: {
16736
+ set: function(val) {this._signal("changeOverwrite");},
16737
+ initialValue: false
16738
+ },
16739
+ newLineMode: {
16740
+ set: function(val) {this.doc.setNewLineMode(val)},
16741
+ get: function() {return this.doc.getNewLineMode()},
16742
+ handlesSet: true
16743
+ },
16744
+ mode: {
16745
+ set: function(val) { this.setMode(val) },
16746
+ get: function() { return this.$modeId }
16747
+ }
16748
+ });
16749
+
16750
+ exports.EditSession = EditSession;
16751
+ });
16752
+
16753
+ ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) {
16754
+ "use strict";
16755
+
16756
+ var lang = acequire("./lib/lang");
16757
+ var oop = acequire("./lib/oop");
16758
+ var Range = acequire("./range").Range;
16759
+
16760
+ var Search = function() {
16761
+ this.$options = {};
16762
+ };
16763
+
16764
+ (function() {
16765
+ this.set = function(options) {
16766
+ oop.mixin(this.$options, options);
16767
+ return this;
16768
+ };
16769
+ this.getOptions = function() {
16770
+ return lang.copyObject(this.$options);
16771
+ };
16772
+ this.setOptions = function(options) {
16773
+ this.$options = options;
16774
+ };
16775
+ this.find = function(session) {
16776
+ var iterator = this.$matchIterator(session, this.$options);
16777
+
16778
+ if (!iterator)
16779
+ return false;
16780
+
16781
+ var firstRange = null;
16782
+ iterator.forEach(function(range, row, offset) {
16783
+ if (!range.start) {
16784
+ var column = range.offset + (offset || 0);
16785
+ firstRange = new Range(row, column, row, column+range.length);
16786
+ } else
16787
+ firstRange = range;
16788
+ return true;
16789
+ });
16790
+
16791
+ return firstRange;
16792
+ };
16793
+ this.findAll = function(session) {
16794
+ var options = this.$options;
16795
+ if (!options.needle)
16796
+ return [];
16797
+ this.$assembleRegExp(options);
16798
+
16799
+ var range = options.range;
16800
+ var lines = range
16801
+ ? session.getLines(range.start.row, range.end.row)
16802
+ : session.doc.getAllLines();
16803
+
16804
+ var ranges = [];
16805
+ var re = options.re;
16806
+ if (options.$isMultiLine) {
16807
+ var len = re.length;
16808
+ var maxRow = lines.length - len;
16809
+ var prevRange;
16810
+ outer: for (var row = re.offset || 0; row <= maxRow; row++) {
16811
+ for (var j = 0; j < len; j++)
16812
+ if (lines[row + j].search(re[j]) == -1)
16813
+ continue outer;
16814
+
16815
+ var startLine = lines[row];
16816
+ var line = lines[row + len - 1];
16817
+ var startIndex = startLine.length - startLine.match(re[0])[0].length;
16818
+ var endIndex = line.match(re[len - 1])[0].length;
16819
+
16820
+ if (prevRange && prevRange.end.row === row &&
16821
+ prevRange.end.column > startIndex
16822
+ ) {
16823
+ continue;
16824
+ }
16825
+ ranges.push(prevRange = new Range(
16826
+ row, startIndex, row + len - 1, endIndex
16827
+ ));
16828
+ if (len > 2)
16829
+ row = row + len - 2;
16830
+ }
16831
+ } else {
16832
+ for (var i = 0; i < lines.length; i++) {
16833
+ var matches = lang.getMatchOffsets(lines[i], re);
16834
+ for (var j = 0; j < matches.length; j++) {
16835
+ var match = matches[j];
16836
+ ranges.push(new Range(i, match.offset, i, match.offset + match.length));
16837
+ }
16838
+ }
16839
+ }
16840
+
16841
+ if (range) {
16842
+ var startColumn = range.start.column;
16843
+ var endColumn = range.start.column;
16844
+ var i = 0, j = ranges.length - 1;
16845
+ while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row)
16846
+ i++;
16847
+
16848
+ while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row)
16849
+ j--;
16850
+
16851
+ ranges = ranges.slice(i, j + 1);
16852
+ for (i = 0, j = ranges.length; i < j; i++) {
16853
+ ranges[i].start.row += range.start.row;
16854
+ ranges[i].end.row += range.start.row;
16855
+ }
16856
+ }
16857
+
16858
+ return ranges;
16859
+ };
16860
+ this.replace = function(input, replacement) {
16861
+ var options = this.$options;
16862
+
16863
+ var re = this.$assembleRegExp(options);
16864
+ if (options.$isMultiLine)
16865
+ return replacement;
16866
+
16867
+ if (!re)
16868
+ return;
16869
+
16870
+ var match = re.exec(input);
16871
+ if (!match || match[0].length != input.length)
16872
+ return null;
16873
+
16874
+ replacement = input.replace(re, replacement);
16875
+ if (options.preserveCase) {
16876
+ replacement = replacement.split("");
16877
+ for (var i = Math.min(input.length, input.length); i--; ) {
16878
+ var ch = input[i];
16879
+ if (ch && ch.toLowerCase() != ch)
16880
+ replacement[i] = replacement[i].toUpperCase();
16881
+ else
16882
+ replacement[i] = replacement[i].toLowerCase();
16883
+ }
16884
+ replacement = replacement.join("");
16885
+ }
16886
+
16887
+ return replacement;
16888
+ };
16889
+
16890
+ this.$matchIterator = function(session, options) {
16891
+ var re = this.$assembleRegExp(options);
16892
+ if (!re)
16893
+ return false;
16894
+
16895
+ var self = this, callback, backwards = options.backwards;
16896
+
16897
+ if (options.$isMultiLine) {
16898
+ var len = re.length;
16899
+ var matchIterator = function(line, row, offset) {
16900
+ var startIndex = line.search(re[0]);
16901
+ if (startIndex == -1)
16902
+ return;
16903
+ for (var i = 1; i < len; i++) {
16904
+ line = session.getLine(row + i);
16905
+ if (line.search(re[i]) == -1)
16906
+ return;
16907
+ }
16908
+
16909
+ var endIndex = line.match(re[len - 1])[0].length;
16910
+
16911
+ var range = new Range(row, startIndex, row + len - 1, endIndex);
16912
+ if (re.offset == 1) {
16913
+ range.start.row--;
16914
+ range.start.column = Number.MAX_VALUE;
16915
+ } else if (offset)
16916
+ range.start.column += offset;
16917
+
16918
+ if (callback(range))
16919
+ return true;
16920
+ };
16921
+ } else if (backwards) {
16922
+ var matchIterator = function(line, row, startIndex) {
16923
+ var matches = lang.getMatchOffsets(line, re);
16924
+ for (var i = matches.length-1; i >= 0; i--)
16925
+ if (callback(matches[i], row, startIndex))
16926
+ return true;
16927
+ };
16928
+ } else {
16929
+ var matchIterator = function(line, row, startIndex) {
16930
+ var matches = lang.getMatchOffsets(line, re);
16931
+ for (var i = 0; i < matches.length; i++)
16932
+ if (callback(matches[i], row, startIndex))
16933
+ return true;
16934
+ };
16935
+ }
16936
+
16937
+ return {
16938
+ forEach: function(_callback) {
16939
+ callback = _callback;
16940
+ self.$lineIterator(session, options).forEach(matchIterator);
16941
+ }
16942
+ };
16943
+ };
16944
+
16945
+ this.$assembleRegExp = function(options, $disableFakeMultiline) {
16946
+ if (options.needle instanceof RegExp)
16947
+ return options.re = options.needle;
16948
+
16949
+ var needle = options.needle;
16950
+
16951
+ if (!options.needle)
16952
+ return options.re = false;
16953
+
16954
+ if (!options.regExp)
16955
+ needle = lang.escapeRegExp(needle);
16956
+
16957
+ if (options.wholeWord)
16958
+ needle = "\\b" + needle + "\\b";
16959
+
16960
+ var modifier = options.caseSensitive ? "gm" : "gmi";
16961
+
16962
+ options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle);
16963
+ if (options.$isMultiLine)
16964
+ return options.re = this.$assembleMultilineRegExp(needle, modifier);
16965
+
16966
+ try {
16967
+ var re = new RegExp(needle, modifier);
16968
+ } catch(e) {
16969
+ re = false;
16970
+ }
16971
+ return options.re = re;
16972
+ };
16973
+
16974
+ this.$assembleMultilineRegExp = function(needle, modifier) {
16975
+ var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n");
16976
+ var re = [];
16977
+ for (var i = 0; i < parts.length; i++) try {
16978
+ re.push(new RegExp(parts[i], modifier));
16979
+ } catch(e) {
16980
+ return false;
16981
+ }
16982
+ if (parts[0] == "") {
16983
+ re.shift();
16984
+ re.offset = 1;
16985
+ } else {
16986
+ re.offset = 0;
16987
+ }
16988
+ return re;
16989
+ };
16990
+
16991
+ this.$lineIterator = function(session, options) {
16992
+ var backwards = options.backwards == true;
16993
+ var skipCurrent = options.skipCurrent != false;
16994
+
16995
+ var range = options.range;
16996
+ var start = options.start;
16997
+ if (!start)
16998
+ start = range ? range[backwards ? "end" : "start"] : session.selection.getRange();
16999
+
17000
+ if (start.start)
17001
+ start = start[skipCurrent != backwards ? "end" : "start"];
17002
+
17003
+ var firstRow = range ? range.start.row : 0;
17004
+ var lastRow = range ? range.end.row : session.getLength() - 1;
17005
+
17006
+ var forEach = backwards ? function(callback) {
17007
+ var row = start.row;
17008
+
17009
+ var line = session.getLine(row).substring(0, start.column);
17010
+ if (callback(line, row))
17011
+ return;
17012
+
17013
+ for (row--; row >= firstRow; row--)
17014
+ if (callback(session.getLine(row), row))
17015
+ return;
17016
+
17017
+ if (options.wrap == false)
17018
+ return;
17019
+
17020
+ for (row = lastRow, firstRow = start.row; row >= firstRow; row--)
17021
+ if (callback(session.getLine(row), row))
17022
+ return;
17023
+ } : function(callback) {
17024
+ var row = start.row;
17025
+
17026
+ var line = session.getLine(row).substr(start.column);
17027
+ if (callback(line, row, start.column))
17028
+ return;
17029
+
17030
+ for (row = row+1; row <= lastRow; row++)
17031
+ if (callback(session.getLine(row), row))
17032
+ return;
17033
+
17034
+ if (options.wrap == false)
17035
+ return;
17036
+
17037
+ for (row = firstRow, lastRow = start.row; row <= lastRow; row++)
17038
+ if (callback(session.getLine(row), row))
17039
+ return;
17040
+ };
17041
+
17042
+ return {forEach: forEach};
17043
+ };
17044
+
17045
+ }).call(Search.prototype);
17046
+
17047
+ exports.Search = Search;
17048
+ });
17049
+
17050
+ ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) {
17051
+ "use strict";
17052
+
17053
+ var keyUtil = acequire("../lib/keys");
17054
+ var useragent = acequire("../lib/useragent");
17055
+ var KEY_MODS = keyUtil.KEY_MODS;
17056
+
17057
+ function HashHandler(config, platform) {
17058
+ this.platform = platform || (useragent.isMac ? "mac" : "win");
17059
+ this.commands = {};
17060
+ this.commandKeyBinding = {};
17061
+ this.addCommands(config);
17062
+ this.$singleCommand = true;
17063
+ }
17064
+
17065
+ function MultiHashHandler(config, platform) {
17066
+ HashHandler.call(this, config, platform);
17067
+ this.$singleCommand = false;
17068
+ }
17069
+
17070
+ MultiHashHandler.prototype = HashHandler.prototype;
17071
+
17072
+ (function() {
17073
+
17074
+
17075
+ this.addCommand = function(command) {
17076
+ if (this.commands[command.name])
17077
+ this.removeCommand(command);
17078
+
17079
+ this.commands[command.name] = command;
17080
+
17081
+ if (command.bindKey)
17082
+ this._buildKeyHash(command);
17083
+ };
17084
+
17085
+ this.removeCommand = function(command, keepCommand) {
17086
+ var name = command && (typeof command === 'string' ? command : command.name);
17087
+ command = this.commands[name];
17088
+ if (!keepCommand)
17089
+ delete this.commands[name];
17090
+ var ckb = this.commandKeyBinding;
17091
+ for (var keyId in ckb) {
17092
+ var cmdGroup = ckb[keyId];
17093
+ if (cmdGroup == command) {
17094
+ delete ckb[keyId];
17095
+ } else if (Array.isArray(cmdGroup)) {
17096
+ var i = cmdGroup.indexOf(command);
17097
+ if (i != -1) {
17098
+ cmdGroup.splice(i, 1);
17099
+ if (cmdGroup.length == 1)
17100
+ ckb[keyId] = cmdGroup[0];
17101
+ }
17102
+ }
17103
+ }
17104
+ };
17105
+
17106
+ this.bindKey = function(key, command, asDefault) {
17107
+ if (typeof key == "object")
17108
+ key = key[this.platform];
17109
+ if (!key)
17110
+ return;
17111
+ if (typeof command == "function")
17112
+ return this.addCommand({exec: command, bindKey: key, name: command.name || key});
17113
+
17114
+ key.split("|").forEach(function(keyPart) {
17115
+ var chain = "";
17116
+ if (keyPart.indexOf(" ") != -1) {
17117
+ var parts = keyPart.split(/\s+/);
17118
+ keyPart = parts.pop();
17119
+ parts.forEach(function(keyPart) {
17120
+ var binding = this.parseKeys(keyPart);
17121
+ var id = KEY_MODS[binding.hashId] + binding.key;
17122
+ chain += (chain ? " " : "") + id;
17123
+ this._addCommandToBinding(chain, "chainKeys");
17124
+ }, this);
17125
+ chain += " ";
17126
+ }
17127
+ var binding = this.parseKeys(keyPart);
17128
+ var id = KEY_MODS[binding.hashId] + binding.key;
17129
+ this._addCommandToBinding(chain + id, command, asDefault);
17130
+ }, this);
17131
+ };
17132
+
17133
+ this._addCommandToBinding = function(keyId, command, asDefault) {
17134
+ var ckb = this.commandKeyBinding, i;
17135
+ if (!command) {
17136
+ delete ckb[keyId];
17137
+ } else if (!ckb[keyId] || this.$singleCommand) {
17138
+ ckb[keyId] = command;
17139
+ } else {
17140
+ if (!Array.isArray(ckb[keyId])) {
17141
+ ckb[keyId] = [ckb[keyId]];
17142
+ } else if ((i = ckb[keyId].indexOf(command)) != -1) {
17143
+ ckb[keyId].splice(i, 1);
17144
+ }
17145
+
17146
+ if (asDefault || command.isDefault)
17147
+ ckb[keyId].unshift(command);
17148
+ else
17149
+ ckb[keyId].push(command);
17150
+ }
17151
+ };
17152
+
17153
+ this.addCommands = function(commands) {
17154
+ commands && Object.keys(commands).forEach(function(name) {
17155
+ var command = commands[name];
17156
+ if (!command)
17157
+ return;
17158
+
17159
+ if (typeof command === "string")
17160
+ return this.bindKey(command, name);
17161
+
17162
+ if (typeof command === "function")
17163
+ command = { exec: command };
17164
+
17165
+ if (typeof command !== "object")
17166
+ return;
17167
+
17168
+ if (!command.name)
17169
+ command.name = name;
17170
+
17171
+ this.addCommand(command);
17172
+ }, this);
17173
+ };
17174
+
17175
+ this.removeCommands = function(commands) {
17176
+ Object.keys(commands).forEach(function(name) {
17177
+ this.removeCommand(commands[name]);
17178
+ }, this);
17179
+ };
17180
+
17181
+ this.bindKeys = function(keyList) {
17182
+ Object.keys(keyList).forEach(function(key) {
17183
+ this.bindKey(key, keyList[key]);
17184
+ }, this);
17185
+ };
17186
+
17187
+ this._buildKeyHash = function(command) {
17188
+ this.bindKey(command.bindKey, command);
17189
+ };
17190
+ this.parseKeys = function(keys) {
17191
+ var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x});
17192
+ var key = parts.pop();
17193
+
17194
+ var keyCode = keyUtil[key];
17195
+ if (keyUtil.FUNCTION_KEYS[keyCode])
17196
+ key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase();
17197
+ else if (!parts.length)
17198
+ return {key: key, hashId: -1};
17199
+ else if (parts.length == 1 && parts[0] == "shift")
17200
+ return {key: key.toUpperCase(), hashId: -1};
17201
+
17202
+ var hashId = 0;
17203
+ for (var i = parts.length; i--;) {
17204
+ var modifier = keyUtil.KEY_MODS[parts[i]];
17205
+ if (modifier == null) {
17206
+ if (typeof console != "undefined")
17207
+ console.error("invalid modifier " + parts[i] + " in " + keys);
17208
+ return false;
17209
+ }
17210
+ hashId |= modifier;
17211
+ }
17212
+ return {key: key, hashId: hashId};
17213
+ };
17214
+
17215
+ this.findKeyCommand = function findKeyCommand(hashId, keyString) {
17216
+ var key = KEY_MODS[hashId] + keyString;
17217
+ return this.commandKeyBinding[key];
17218
+ };
17219
+
17220
+ this.handleKeyboard = function(data, hashId, keyString, keyCode) {
17221
+ var key = KEY_MODS[hashId] + keyString;
17222
+ var command = this.commandKeyBinding[key];
17223
+ if (data.$keyChain) {
17224
+ data.$keyChain += " " + key;
17225
+ command = this.commandKeyBinding[data.$keyChain] || command;
17226
+ }
17227
+
17228
+ if (command) {
17229
+ if (command == "chainKeys" || command[command.length - 1] == "chainKeys") {
17230
+ data.$keyChain = data.$keyChain || key;
17231
+ return {command: "null"};
17232
+ }
17233
+ }
17234
+
17235
+ if (data.$keyChain && keyCode > 0)
17236
+ data.$keyChain = "";
17237
+ return {command: command};
17238
+ };
17239
+
17240
+ }).call(HashHandler.prototype);
17241
+
17242
+ exports.HashHandler = HashHandler;
17243
+ exports.MultiHashHandler = MultiHashHandler;
17244
+ });
17245
+
17246
+ ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(acequire, exports, module) {
17247
+ "use strict";
17248
+
17249
+ var oop = acequire("../lib/oop");
17250
+ var MultiHashHandler = acequire("../keyboard/hash_handler").MultiHashHandler;
17251
+ var EventEmitter = acequire("../lib/event_emitter").EventEmitter;
17252
+
17253
+ var CommandManager = function(platform, commands) {
17254
+ MultiHashHandler.call(this, commands, platform);
17255
+ this.byName = this.commands;
17256
+ this.setDefaultHandler("exec", function(e) {
17257
+ return e.command.exec(e.editor, e.args || {});
17258
+ });
17259
+ };
17260
+
17261
+ oop.inherits(CommandManager, MultiHashHandler);
17262
+
17263
+ (function() {
17264
+
17265
+ oop.implement(this, EventEmitter);
17266
+
17267
+ this.exec = function(command, editor, args) {
17268
+ if (Array.isArray(command)) {
17269
+ for (var i = command.length; i--; ) {
17270
+ if (this.exec(command[i], editor, args)) return true;
17271
+ }
17272
+ return false;
17273
+ }
17274
+
17275
+ if (typeof command === "string")
17276
+ command = this.commands[command];
17277
+
17278
+ if (!command)
17279
+ return false;
17280
+
17281
+ if (editor && editor.$readOnly && !command.readOnly)
17282
+ return false;
17283
+
17284
+ var e = {editor: editor, command: command, args: args};
17285
+ e.returnValue = this._emit("exec", e);
17286
+ this._signal("afterExec", e);
17287
+
17288
+ return e.returnValue === false ? false : true;
17289
+ };
17290
+
17291
+ this.toggleRecording = function(editor) {
17292
+ if (this.$inReplay)
17293
+ return;
17294
+
17295
+ editor && editor._emit("changeStatus");
17296
+ if (this.recording) {
17297
+ this.macro.pop();
17298
+ this.removeEventListener("exec", this.$addCommandToMacro);
17299
+
17300
+ if (!this.macro.length)
17301
+ this.macro = this.oldMacro;
17302
+
17303
+ return this.recording = false;
17304
+ }
17305
+ if (!this.$addCommandToMacro) {
17306
+ this.$addCommandToMacro = function(e) {
17307
+ this.macro.push([e.command, e.args]);
17308
+ }.bind(this);
17309
+ }
17310
+
17311
+ this.oldMacro = this.macro;
17312
+ this.macro = [];
17313
+ this.on("exec", this.$addCommandToMacro);
17314
+ return this.recording = true;
17315
+ };
17316
+
17317
+ this.replay = function(editor) {
17318
+ if (this.$inReplay || !this.macro)
17319
+ return;
17320
+
17321
+ if (this.recording)
17322
+ return this.toggleRecording(editor);
17323
+
17324
+ try {
17325
+ this.$inReplay = true;
17326
+ this.macro.forEach(function(x) {
17327
+ if (typeof x == "string")
17328
+ this.exec(x, editor);
17329
+ else
17330
+ this.exec(x[0], editor, x[1]);
17331
+ }, this);
17332
+ } finally {
17333
+ this.$inReplay = false;
17334
+ }
17335
+ };
17336
+
17337
+ this.trimMacro = function(m) {
17338
+ return m.map(function(x){
17339
+ if (typeof x[0] != "string")
17340
+ x[0] = x[0].name;
17341
+ if (!x[1])
17342
+ x = x[0];
17343
+ return x;
17344
+ });
17345
+ };
17346
+
17347
+ }).call(CommandManager.prototype);
17348
+
17349
+ exports.CommandManager = CommandManager;
17350
+
17351
+ });
17352
+
17353
+ ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(acequire, exports, module) {
17354
+ "use strict";
17355
+
17356
+ var lang = acequire("../lib/lang");
17357
+ var config = acequire("../config");
17358
+ var Range = acequire("../range").Range;
17359
+
17360
+ function bindKey(win, mac) {
17361
+ return {win: win, mac: mac};
17362
+ }
17363
+ exports.commands = [{
17364
+ name: "showSettingsMenu",
17365
+ bindKey: bindKey("Ctrl-,", "Command-,"),
17366
+ exec: function(editor) {
17367
+ config.loadModule("ace/ext/settings_menu", function(module) {
17368
+ module.init(editor);
17369
+ editor.showSettingsMenu();
17370
+ });
17371
+ },
17372
+ readOnly: true
17373
+ }, {
17374
+ name: "goToNextError",
17375
+ bindKey: bindKey("Alt-E", "Ctrl-E"),
17376
+ exec: function(editor) {
17377
+ config.loadModule("ace/ext/error_marker", function(module) {
17378
+ module.showErrorMarker(editor, 1);
17379
+ });
17380
+ },
17381
+ scrollIntoView: "animate",
17382
+ readOnly: true
17383
+ }, {
17384
+ name: "goToPreviousError",
17385
+ bindKey: bindKey("Alt-Shift-E", "Ctrl-Shift-E"),
17386
+ exec: function(editor) {
17387
+ config.loadModule("ace/ext/error_marker", function(module) {
17388
+ module.showErrorMarker(editor, -1);
17389
+ });
17390
+ },
17391
+ scrollIntoView: "animate",
17392
+ readOnly: true
17393
+ }, {
17394
+ name: "selectall",
17395
+ bindKey: bindKey("Ctrl-A", "Command-A"),
17396
+ exec: function(editor) { editor.selectAll(); },
17397
+ readOnly: true
17398
+ }, {
17399
+ name: "centerselection",
17400
+ bindKey: bindKey(null, "Ctrl-L"),
17401
+ exec: function(editor) { editor.centerSelection(); },
17402
+ readOnly: true
17403
+ }, {
17404
+ name: "gotoline",
17405
+ bindKey: bindKey("Ctrl-L", "Command-L"),
17406
+ exec: function(editor) {
17407
+ var line = parseInt(prompt("Enter line number:"), 10);
17408
+ if (!isNaN(line)) {
17409
+ editor.gotoLine(line);
17410
+ }
17411
+ },
17412
+ readOnly: true
17413
+ }, {
17414
+ name: "fold",
17415
+ bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
17416
+ exec: function(editor) { editor.session.toggleFold(false); },
17417
+ scrollIntoView: "center",
17418
+ readOnly: true
17419
+ }, {
17420
+ name: "unfold",
17421
+ bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
17422
+ exec: function(editor) { editor.session.toggleFold(true); },
17423
+ scrollIntoView: "center",
17424
+ readOnly: true
17425
+ }, {
17426
+ name: "toggleFoldWidget",
17427
+ bindKey: bindKey("F2", "F2"),
17428
+ exec: function(editor) { editor.session.toggleFoldWidget(); },
17429
+ scrollIntoView: "center",
17430
+ readOnly: true
17431
+ }, {
17432
+ name: "toggleParentFoldWidget",
17433
+ bindKey: bindKey("Alt-F2", "Alt-F2"),
17434
+ exec: function(editor) { editor.session.toggleFoldWidget(true); },
17435
+ scrollIntoView: "center",
17436
+ readOnly: true
17437
+ }, {
17438
+ name: "foldall",
17439
+ bindKey: bindKey("Ctrl-Alt-0", "Ctrl-Command-Option-0"),
17440
+ exec: function(editor) { editor.session.foldAll(); },
17441
+ scrollIntoView: "center",
17442
+ readOnly: true
17443
+ }, {
17444
+ name: "foldOther",
17445
+ bindKey: bindKey("Alt-0", "Command-Option-0"),
17446
+ exec: function(editor) {
17447
+ editor.session.foldAll();
17448
+ editor.session.unfold(editor.selection.getAllRanges());
17449
+ },
17450
+ scrollIntoView: "center",
17451
+ readOnly: true
17452
+ }, {
17453
+ name: "unfoldall",
17454
+ bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
17455
+ exec: function(editor) { editor.session.unfold(); },
17456
+ scrollIntoView: "center",
17457
+ readOnly: true
17458
+ }, {
17459
+ name: "findnext",
17460
+ bindKey: bindKey("Ctrl-K", "Command-G"),
17461
+ exec: function(editor) { editor.findNext(); },
17462
+ multiSelectAction: "forEach",
17463
+ scrollIntoView: "center",
17464
+ readOnly: true
17465
+ }, {
17466
+ name: "findprevious",
17467
+ bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
17468
+ exec: function(editor) { editor.findPrevious(); },
17469
+ multiSelectAction: "forEach",
17470
+ scrollIntoView: "center",
17471
+ readOnly: true
17472
+ }, {
17473
+ name: "selectOrFindNext",
17474
+ bindKey: bindKey("Alt-K", "Ctrl-G"),
17475
+ exec: function(editor) {
17476
+ if (editor.selection.isEmpty())
17477
+ editor.selection.selectWord();
17478
+ else
17479
+ editor.findNext();
17480
+ },
17481
+ readOnly: true
17482
+ }, {
17483
+ name: "selectOrFindPrevious",
17484
+ bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"),
17485
+ exec: function(editor) {
17486
+ if (editor.selection.isEmpty())
17487
+ editor.selection.selectWord();
17488
+ else
17489
+ editor.findPrevious();
17490
+ },
17491
+ readOnly: true
17492
+ }, {
17493
+ name: "find",
17494
+ bindKey: bindKey("Ctrl-F", "Command-F"),
17495
+ exec: function(editor) {
17496
+ config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)});
17497
+ },
17498
+ readOnly: true
17499
+ }, {
17500
+ name: "overwrite",
17501
+ bindKey: "Insert",
17502
+ exec: function(editor) { editor.toggleOverwrite(); },
17503
+ readOnly: true
17504
+ }, {
17505
+ name: "selecttostart",
17506
+ bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
17507
+ exec: function(editor) { editor.getSelection().selectFileStart(); },
17508
+ multiSelectAction: "forEach",
17509
+ readOnly: true,
17510
+ scrollIntoView: "animate",
17511
+ aceCommandGroup: "fileJump"
17512
+ }, {
17513
+ name: "gotostart",
17514
+ bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
17515
+ exec: function(editor) { editor.navigateFileStart(); },
17516
+ multiSelectAction: "forEach",
17517
+ readOnly: true,
17518
+ scrollIntoView: "animate",
17519
+ aceCommandGroup: "fileJump"
17520
+ }, {
17521
+ name: "selectup",
17522
+ bindKey: bindKey("Shift-Up", "Shift-Up"),
17523
+ exec: function(editor) { editor.getSelection().selectUp(); },
17524
+ multiSelectAction: "forEach",
17525
+ readOnly: true
17526
+ }, {
17527
+ name: "golineup",
17528
+ bindKey: bindKey("Up", "Up|Ctrl-P"),
17529
+ exec: function(editor, args) { editor.navigateUp(args.times); },
17530
+ multiSelectAction: "forEach",
17531
+ readOnly: true
17532
+ }, {
17533
+ name: "selecttoend",
17534
+ bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
17535
+ exec: function(editor) { editor.getSelection().selectFileEnd(); },
17536
+ multiSelectAction: "forEach",
17537
+ readOnly: true,
17538
+ scrollIntoView: "animate",
17539
+ aceCommandGroup: "fileJump"
17540
+ }, {
17541
+ name: "gotoend",
17542
+ bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
17543
+ exec: function(editor) { editor.navigateFileEnd(); },
17544
+ multiSelectAction: "forEach",
17545
+ readOnly: true,
17546
+ scrollIntoView: "animate",
17547
+ aceCommandGroup: "fileJump"
17548
+ }, {
17549
+ name: "selectdown",
17550
+ bindKey: bindKey("Shift-Down", "Shift-Down"),
17551
+ exec: function(editor) { editor.getSelection().selectDown(); },
17552
+ multiSelectAction: "forEach",
17553
+ scrollIntoView: "cursor",
17554
+ readOnly: true
17555
+ }, {
17556
+ name: "golinedown",
17557
+ bindKey: bindKey("Down", "Down|Ctrl-N"),
17558
+ exec: function(editor, args) { editor.navigateDown(args.times); },
17559
+ multiSelectAction: "forEach",
17560
+ scrollIntoView: "cursor",
17561
+ readOnly: true
17562
+ }, {
17563
+ name: "selectwordleft",
17564
+ bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
17565
+ exec: function(editor) { editor.getSelection().selectWordLeft(); },
17566
+ multiSelectAction: "forEach",
17567
+ scrollIntoView: "cursor",
17568
+ readOnly: true
17569
+ }, {
17570
+ name: "gotowordleft",
17571
+ bindKey: bindKey("Ctrl-Left", "Option-Left"),
17572
+ exec: function(editor) { editor.navigateWordLeft(); },
17573
+ multiSelectAction: "forEach",
17574
+ scrollIntoView: "cursor",
17575
+ readOnly: true
17576
+ }, {
17577
+ name: "selecttolinestart",
17578
+ bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
17579
+ exec: function(editor) { editor.getSelection().selectLineStart(); },
17580
+ multiSelectAction: "forEach",
17581
+ scrollIntoView: "cursor",
17582
+ readOnly: true
17583
+ }, {
17584
+ name: "gotolinestart",
17585
+ bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
17586
+ exec: function(editor) { editor.navigateLineStart(); },
17587
+ multiSelectAction: "forEach",
17588
+ scrollIntoView: "cursor",
17589
+ readOnly: true
17590
+ }, {
17591
+ name: "selectleft",
17592
+ bindKey: bindKey("Shift-Left", "Shift-Left"),
17593
+ exec: function(editor) { editor.getSelection().selectLeft(); },
17594
+ multiSelectAction: "forEach",
17595
+ scrollIntoView: "cursor",
17596
+ readOnly: true
17597
+ }, {
17598
+ name: "gotoleft",
17599
+ bindKey: bindKey("Left", "Left|Ctrl-B"),
17600
+ exec: function(editor, args) { editor.navigateLeft(args.times); },
17601
+ multiSelectAction: "forEach",
17602
+ scrollIntoView: "cursor",
17603
+ readOnly: true
17604
+ }, {
17605
+ name: "selectwordright",
17606
+ bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
17607
+ exec: function(editor) { editor.getSelection().selectWordRight(); },
17608
+ multiSelectAction: "forEach",
17609
+ scrollIntoView: "cursor",
17610
+ readOnly: true
17611
+ }, {
17612
+ name: "gotowordright",
17613
+ bindKey: bindKey("Ctrl-Right", "Option-Right"),
17614
+ exec: function(editor) { editor.navigateWordRight(); },
17615
+ multiSelectAction: "forEach",
17616
+ scrollIntoView: "cursor",
17617
+ readOnly: true
17618
+ }, {
17619
+ name: "selecttolineend",
17620
+ bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
17621
+ exec: function(editor) { editor.getSelection().selectLineEnd(); },
17622
+ multiSelectAction: "forEach",
17623
+ scrollIntoView: "cursor",
17624
+ readOnly: true
17625
+ }, {
17626
+ name: "gotolineend",
17627
+ bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
17628
+ exec: function(editor) { editor.navigateLineEnd(); },
17629
+ multiSelectAction: "forEach",
17630
+ scrollIntoView: "cursor",
17631
+ readOnly: true
17632
+ }, {
17633
+ name: "selectright",
17634
+ bindKey: bindKey("Shift-Right", "Shift-Right"),
17635
+ exec: function(editor) { editor.getSelection().selectRight(); },
17636
+ multiSelectAction: "forEach",
17637
+ scrollIntoView: "cursor",
17638
+ readOnly: true
17639
+ }, {
17640
+ name: "gotoright",
17641
+ bindKey: bindKey("Right", "Right|Ctrl-F"),
17642
+ exec: function(editor, args) { editor.navigateRight(args.times); },
17643
+ multiSelectAction: "forEach",
17644
+ scrollIntoView: "cursor",
17645
+ readOnly: true
17646
+ }, {
17647
+ name: "selectpagedown",
17648
+ bindKey: "Shift-PageDown",
17649
+ exec: function(editor) { editor.selectPageDown(); },
17650
+ readOnly: true
17651
+ }, {
17652
+ name: "pagedown",
17653
+ bindKey: bindKey(null, "Option-PageDown"),
17654
+ exec: function(editor) { editor.scrollPageDown(); },
17655
+ readOnly: true
17656
+ }, {
17657
+ name: "gotopagedown",
17658
+ bindKey: bindKey("PageDown", "PageDown|Ctrl-V"),
17659
+ exec: function(editor) { editor.gotoPageDown(); },
17660
+ readOnly: true
17661
+ }, {
17662
+ name: "selectpageup",
17663
+ bindKey: "Shift-PageUp",
17664
+ exec: function(editor) { editor.selectPageUp(); },
17665
+ readOnly: true
17666
+ }, {
17667
+ name: "pageup",
17668
+ bindKey: bindKey(null, "Option-PageUp"),
17669
+ exec: function(editor) { editor.scrollPageUp(); },
17670
+ readOnly: true
17671
+ }, {
17672
+ name: "gotopageup",
17673
+ bindKey: "PageUp",
17674
+ exec: function(editor) { editor.gotoPageUp(); },
17675
+ readOnly: true
17676
+ }, {
17677
+ name: "scrollup",
17678
+ bindKey: bindKey("Ctrl-Up", null),
17679
+ exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); },
17680
+ readOnly: true
17681
+ }, {
17682
+ name: "scrolldown",
17683
+ bindKey: bindKey("Ctrl-Down", null),
17684
+ exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); },
17685
+ readOnly: true
17686
+ }, {
17687
+ name: "selectlinestart",
17688
+ bindKey: "Shift-Home",
17689
+ exec: function(editor) { editor.getSelection().selectLineStart(); },
17690
+ multiSelectAction: "forEach",
17691
+ scrollIntoView: "cursor",
17692
+ readOnly: true
17693
+ }, {
17694
+ name: "selectlineend",
17695
+ bindKey: "Shift-End",
17696
+ exec: function(editor) { editor.getSelection().selectLineEnd(); },
17697
+ multiSelectAction: "forEach",
17698
+ scrollIntoView: "cursor",
17699
+ readOnly: true
17700
+ }, {
17701
+ name: "togglerecording",
17702
+ bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"),
17703
+ exec: function(editor) { editor.commands.toggleRecording(editor); },
17704
+ readOnly: true
17705
+ }, {
17706
+ name: "replaymacro",
17707
+ bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
17708
+ exec: function(editor) { editor.commands.replay(editor); },
17709
+ readOnly: true
17710
+ }, {
17711
+ name: "jumptomatching",
17712
+ bindKey: bindKey("Ctrl-P", "Ctrl-P"),
17713
+ exec: function(editor) { editor.jumpToMatching(); },
17714
+ multiSelectAction: "forEach",
17715
+ readOnly: true
17716
+ }, {
17717
+ name: "selecttomatching",
17718
+ bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
17719
+ exec: function(editor) { editor.jumpToMatching(true); },
17720
+ multiSelectAction: "forEach",
17721
+ readOnly: true
17722
+ }, {
17723
+ name: "passKeysToBrowser",
17724
+ bindKey: bindKey("null", "null"),
17725
+ exec: function() {},
17726
+ passEvent: true,
17727
+ readOnly: true
17728
+ },
17729
+ {
17730
+ name: "cut",
17731
+ exec: function(editor) {
17732
+ var range = editor.getSelectionRange();
17733
+ editor._emit("cut", range);
17734
+
17735
+ if (!editor.selection.isEmpty()) {
17736
+ editor.session.remove(range);
17737
+ editor.clearSelection();
17738
+ }
17739
+ },
17740
+ scrollIntoView: "cursor",
17741
+ multiSelectAction: "forEach"
17742
+ }, {
17743
+ name: "removeline",
17744
+ bindKey: bindKey("Ctrl-D", "Command-D"),
17745
+ exec: function(editor) { editor.removeLines(); },
17746
+ scrollIntoView: "cursor",
17747
+ multiSelectAction: "forEachLine"
17748
+ }, {
17749
+ name: "duplicateSelection",
17750
+ bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
17751
+ exec: function(editor) { editor.duplicateSelection(); },
17752
+ scrollIntoView: "cursor",
17753
+ multiSelectAction: "forEach"
17754
+ }, {
17755
+ name: "sortlines",
17756
+ bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
17757
+ exec: function(editor) { editor.sortLines(); },
17758
+ scrollIntoView: "selection",
17759
+ multiSelectAction: "forEachLine"
17760
+ }, {
17761
+ name: "togglecomment",
17762
+ bindKey: bindKey("Ctrl-/", "Command-/"),
17763
+ exec: function(editor) { editor.toggleCommentLines(); },
17764
+ multiSelectAction: "forEachLine",
17765
+ scrollIntoView: "selectionPart"
17766
+ }, {
17767
+ name: "toggleBlockComment",
17768
+ bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
17769
+ exec: function(editor) { editor.toggleBlockComment(); },
17770
+ multiSelectAction: "forEach",
17771
+ scrollIntoView: "selectionPart"
17772
+ }, {
17773
+ name: "modifyNumberUp",
17774
+ bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
17775
+ exec: function(editor) { editor.modifyNumber(1); },
17776
+ multiSelectAction: "forEach"
17777
+ }, {
17778
+ name: "modifyNumberDown",
17779
+ bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
17780
+ exec: function(editor) { editor.modifyNumber(-1); },
17781
+ multiSelectAction: "forEach"
17782
+ }, {
17783
+ name: "replace",
17784
+ bindKey: bindKey("Ctrl-H", "Command-Option-F"),
17785
+ exec: function(editor) {
17786
+ config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)});
17787
+ }
17788
+ }, {
17789
+ name: "undo",
17790
+ bindKey: bindKey("Ctrl-Z", "Command-Z"),
17791
+ exec: function(editor) { editor.undo(); }
17792
+ }, {
17793
+ name: "redo",
17794
+ bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
17795
+ exec: function(editor) { editor.redo(); }
17796
+ }, {
17797
+ name: "copylinesup",
17798
+ bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
17799
+ exec: function(editor) { editor.copyLinesUp(); },
17800
+ scrollIntoView: "cursor"
17801
+ }, {
17802
+ name: "movelinesup",
17803
+ bindKey: bindKey("Alt-Up", "Option-Up"),
17804
+ exec: function(editor) { editor.moveLinesUp(); },
17805
+ scrollIntoView: "cursor"
17806
+ }, {
17807
+ name: "copylinesdown",
17808
+ bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
17809
+ exec: function(editor) { editor.copyLinesDown(); },
17810
+ scrollIntoView: "cursor"
17811
+ }, {
17812
+ name: "movelinesdown",
17813
+ bindKey: bindKey("Alt-Down", "Option-Down"),
17814
+ exec: function(editor) { editor.moveLinesDown(); },
17815
+ scrollIntoView: "cursor"
17816
+ }, {
17817
+ name: "del",
17818
+ bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"),
17819
+ exec: function(editor) { editor.remove("right"); },
17820
+ multiSelectAction: "forEach",
17821
+ scrollIntoView: "cursor"
17822
+ }, {
17823
+ name: "backspace",
17824
+ bindKey: bindKey(
17825
+ "Shift-Backspace|Backspace",
17826
+ "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
17827
+ ),
17828
+ exec: function(editor) { editor.remove("left"); },
17829
+ multiSelectAction: "forEach",
17830
+ scrollIntoView: "cursor"
17831
+ }, {
17832
+ name: "cut_or_delete",
17833
+ bindKey: bindKey("Shift-Delete", null),
17834
+ exec: function(editor) {
17835
+ if (editor.selection.isEmpty()) {
17836
+ editor.remove("left");
17837
+ } else {
17838
+ return false;
17839
+ }
17840
+ },
17841
+ multiSelectAction: "forEach",
17842
+ scrollIntoView: "cursor"
17843
+ }, {
17844
+ name: "removetolinestart",
17845
+ bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
17846
+ exec: function(editor) { editor.removeToLineStart(); },
17847
+ multiSelectAction: "forEach",
17848
+ scrollIntoView: "cursor"
17849
+ }, {
17850
+ name: "removetolineend",
17851
+ bindKey: bindKey("Alt-Delete", "Ctrl-K"),
17852
+ exec: function(editor) { editor.removeToLineEnd(); },
17853
+ multiSelectAction: "forEach",
17854
+ scrollIntoView: "cursor"
17855
+ }, {
17856
+ name: "removewordleft",
17857
+ bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
17858
+ exec: function(editor) { editor.removeWordLeft(); },
17859
+ multiSelectAction: "forEach",
17860
+ scrollIntoView: "cursor"
17861
+ }, {
17862
+ name: "removewordright",
17863
+ bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
17864
+ exec: function(editor) { editor.removeWordRight(); },
17865
+ multiSelectAction: "forEach",
17866
+ scrollIntoView: "cursor"
17867
+ }, {
17868
+ name: "outdent",
17869
+ bindKey: bindKey("Shift-Tab", "Shift-Tab"),
17870
+ exec: function(editor) { editor.blockOutdent(); },
17871
+ multiSelectAction: "forEach",
17872
+ scrollIntoView: "selectionPart"
17873
+ }, {
17874
+ name: "indent",
17875
+ bindKey: bindKey("Tab", "Tab"),
17876
+ exec: function(editor) { editor.indent(); },
17877
+ multiSelectAction: "forEach",
17878
+ scrollIntoView: "selectionPart"
17879
+ }, {
17880
+ name: "blockoutdent",
17881
+ bindKey: bindKey("Ctrl-[", "Ctrl-["),
17882
+ exec: function(editor) { editor.blockOutdent(); },
17883
+ multiSelectAction: "forEachLine",
17884
+ scrollIntoView: "selectionPart"
17885
+ }, {
17886
+ name: "blockindent",
17887
+ bindKey: bindKey("Ctrl-]", "Ctrl-]"),
17888
+ exec: function(editor) { editor.blockIndent(); },
17889
+ multiSelectAction: "forEachLine",
17890
+ scrollIntoView: "selectionPart"
17891
+ }, {
17892
+ name: "insertstring",
17893
+ exec: function(editor, str) { editor.insert(str); },
17894
+ multiSelectAction: "forEach",
17895
+ scrollIntoView: "cursor"
17896
+ }, {
17897
+ name: "inserttext",
17898
+ exec: function(editor, args) {
17899
+ editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
17900
+ },
17901
+ multiSelectAction: "forEach",
17902
+ scrollIntoView: "cursor"
17903
+ }, {
17904
+ name: "splitline",
17905
+ bindKey: bindKey(null, "Ctrl-O"),
17906
+ exec: function(editor) { editor.splitLine(); },
17907
+ multiSelectAction: "forEach",
17908
+ scrollIntoView: "cursor"
17909
+ }, {
17910
+ name: "transposeletters",
17911
+ bindKey: bindKey("Ctrl-T", "Ctrl-T"),
17912
+ exec: function(editor) { editor.transposeLetters(); },
17913
+ multiSelectAction: function(editor) {editor.transposeSelections(1); },
17914
+ scrollIntoView: "cursor"
17915
+ }, {
17916
+ name: "touppercase",
17917
+ bindKey: bindKey("Ctrl-U", "Ctrl-U"),
17918
+ exec: function(editor) { editor.toUpperCase(); },
17919
+ multiSelectAction: "forEach",
17920
+ scrollIntoView: "cursor"
17921
+ }, {
17922
+ name: "tolowercase",
17923
+ bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
17924
+ exec: function(editor) { editor.toLowerCase(); },
17925
+ multiSelectAction: "forEach",
17926
+ scrollIntoView: "cursor"
17927
+ }, {
17928
+ name: "expandtoline",
17929
+ bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"),
17930
+ exec: function(editor) {
17931
+ var range = editor.selection.getRange();
17932
+
17933
+ range.start.column = range.end.column = 0;
17934
+ range.end.row++;
17935
+ editor.selection.setRange(range, false);
17936
+ },
17937
+ multiSelectAction: "forEach",
17938
+ scrollIntoView: "cursor",
17939
+ readOnly: true
17940
+ }, {
17941
+ name: "joinlines",
17942
+ bindKey: bindKey(null, null),
17943
+ exec: function(editor) {
17944
+ var isBackwards = editor.selection.isBackwards();
17945
+ var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor();
17946
+ var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead();
17947
+ var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length
17948
+ var selectedText = editor.session.doc.getTextRange(editor.selection.getRange());
17949
+ var selectedCount = selectedText.replace(/\n\s*/, " ").length;
17950
+ var insertLine = editor.session.doc.getLine(selectionStart.row);
17951
+
17952
+ for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) {
17953
+ var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i)));
17954
+ if (curLine.length !== 0) {
17955
+ curLine = " " + curLine;
17956
+ }
17957
+ insertLine += curLine;
17958
+ };
17959
+
17960
+ if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) {
17961
+ insertLine += editor.session.doc.getNewLineCharacter();
17962
+ }
17963
+
17964
+ editor.clearSelection();
17965
+ editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine);
17966
+
17967
+ if (selectedCount > 0) {
17968
+ editor.selection.moveCursorTo(selectionStart.row, selectionStart.column);
17969
+ editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount);
17970
+ } else {
17971
+ firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol;
17972
+ editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol);
17973
+ }
17974
+ },
17975
+ multiSelectAction: "forEach",
17976
+ readOnly: true
17977
+ }, {
17978
+ name: "invertSelection",
17979
+ bindKey: bindKey(null, null),
17980
+ exec: function(editor) {
17981
+ var endRow = editor.session.doc.getLength() - 1;
17982
+ var endCol = editor.session.doc.getLine(endRow).length;
17983
+ var ranges = editor.selection.rangeList.ranges;
17984
+ var newRanges = [];
17985
+ if (ranges.length < 1) {
17986
+ ranges = [editor.selection.getRange()];
17987
+ }
17988
+
17989
+ for (var i = 0; i < ranges.length; i++) {
17990
+ if (i == (ranges.length - 1)) {
17991
+ if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) {
17992
+ newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol));
17993
+ }
17994
+ }
17995
+
17996
+ if (i === 0) {
17997
+ if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) {
17998
+ newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column));
17999
+ }
18000
+ } else {
18001
+ newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column));
18002
+ }
18003
+ }
18004
+
18005
+ editor.exitMultiSelectMode();
18006
+ editor.clearSelection();
18007
+
18008
+ for(var i = 0; i < newRanges.length; i++) {
18009
+ editor.selection.addRange(newRanges[i], false);
18010
+ }
18011
+ },
18012
+ readOnly: true,
18013
+ scrollIntoView: "none"
18014
+ }];
18015
+
18016
+ });
18017
+
18018
+ ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config","ace/token_iterator"], function(acequire, exports, module) {
18019
+ "use strict";
18020
+
18021
+ acequire("./lib/fixoldbrowsers");
18022
+
18023
+ var oop = acequire("./lib/oop");
18024
+ var dom = acequire("./lib/dom");
18025
+ var lang = acequire("./lib/lang");
18026
+ var useragent = acequire("./lib/useragent");
18027
+ var TextInput = acequire("./keyboard/textinput").TextInput;
18028
+ var MouseHandler = acequire("./mouse/mouse_handler").MouseHandler;
18029
+ var FoldHandler = acequire("./mouse/fold_handler").FoldHandler;
18030
+ var KeyBinding = acequire("./keyboard/keybinding").KeyBinding;
18031
+ var EditSession = acequire("./edit_session").EditSession;
18032
+ var Search = acequire("./search").Search;
18033
+ var Range = acequire("./range").Range;
18034
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
18035
+ var CommandManager = acequire("./commands/command_manager").CommandManager;
18036
+ var defaultCommands = acequire("./commands/default_commands").commands;
18037
+ var config = acequire("./config");
18038
+ var TokenIterator = acequire("./token_iterator").TokenIterator;
18039
+ var Editor = function(renderer, session) {
18040
+ var container = renderer.getContainerElement();
18041
+ this.container = container;
18042
+ this.renderer = renderer;
18043
+
18044
+ this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
18045
+ this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
18046
+ this.renderer.textarea = this.textInput.getElement();
18047
+ this.keyBinding = new KeyBinding(this);
18048
+ this.$mouseHandler = new MouseHandler(this);
18049
+ new FoldHandler(this);
18050
+
18051
+ this.$blockScrolling = 0;
18052
+ this.$search = new Search().set({
18053
+ wrap: true
18054
+ });
18055
+
18056
+ this.$historyTracker = this.$historyTracker.bind(this);
18057
+ this.commands.on("exec", this.$historyTracker);
18058
+
18059
+ this.$initOperationListeners();
18060
+
18061
+ this._$emitInputEvent = lang.delayedCall(function() {
18062
+ this._signal("input", {});
18063
+ if (this.session && this.session.bgTokenizer)
18064
+ this.session.bgTokenizer.scheduleStart();
18065
+ }.bind(this));
18066
+
18067
+ this.on("change", function(_, _self) {
18068
+ _self._$emitInputEvent.schedule(31);
18069
+ });
18070
+
18071
+ this.setSession(session || new EditSession(""));
18072
+ config.resetOptions(this);
18073
+ config._signal("editor", this);
18074
+ };
18075
+
18076
+ (function(){
18077
+
18078
+ oop.implement(this, EventEmitter);
18079
+
18080
+ this.$initOperationListeners = function() {
18081
+ function last(a) {return a[a.length - 1]}
18082
+
18083
+ this.selections = [];
18084
+ this.commands.on("exec", this.startOperation.bind(this), true);
18085
+ this.commands.on("afterExec", this.endOperation.bind(this), true);
18086
+
18087
+ this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
18088
+
18089
+ this.on("change", function() {
18090
+ this.curOp || this.startOperation();
18091
+ this.curOp.docChanged = true;
18092
+ }.bind(this), true);
18093
+
18094
+ this.on("changeSelection", function() {
18095
+ this.curOp || this.startOperation();
18096
+ this.curOp.selectionChanged = true;
18097
+ }.bind(this), true);
18098
+ };
18099
+
18100
+ this.curOp = null;
18101
+ this.prevOp = {};
18102
+ this.startOperation = function(commadEvent) {
18103
+ if (this.curOp) {
18104
+ if (!commadEvent || this.curOp.command)
18105
+ return;
18106
+ this.prevOp = this.curOp;
18107
+ }
18108
+ if (!commadEvent) {
18109
+ this.previousCommand = null;
18110
+ commadEvent = {};
18111
+ }
18112
+
18113
+ this.$opResetTimer.schedule();
18114
+ this.curOp = {
18115
+ command: commadEvent.command || {},
18116
+ args: commadEvent.args,
18117
+ scrollTop: this.renderer.scrollTop
18118
+ };
18119
+ };
18120
+
18121
+ this.endOperation = function(e) {
18122
+ if (this.curOp) {
18123
+ if (e && e.returnValue === false)
18124
+ return this.curOp = null;
18125
+
18126
+ var command = this.curOp.command;
18127
+ if (command && command.scrollIntoView) {
18128
+ switch (command.scrollIntoView) {
18129
+ case "center":
18130
+ this.renderer.scrollCursorIntoView(null, 0.5);
18131
+ break;
18132
+ case "animate":
18133
+ case "cursor":
18134
+ this.renderer.scrollCursorIntoView();
18135
+ break;
18136
+ case "selectionPart":
18137
+ var range = this.selection.getRange();
18138
+ var config = this.renderer.layerConfig;
18139
+ if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) {
18140
+ this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead);
18141
+ }
18142
+ break;
18143
+ default:
18144
+ break;
18145
+ }
18146
+ if (command.scrollIntoView == "animate")
18147
+ this.renderer.animateScrolling(this.curOp.scrollTop);
18148
+ }
18149
+
18150
+ this.prevOp = this.curOp;
18151
+ this.curOp = null;
18152
+ }
18153
+ };
18154
+ this.$mergeableCommands = ["backspace", "del", "insertstring"];
18155
+ this.$historyTracker = function(e) {
18156
+ if (!this.$mergeUndoDeltas)
18157
+ return;
18158
+
18159
+ var prev = this.prevOp;
18160
+ var mergeableCommands = this.$mergeableCommands;
18161
+ var shouldMerge = prev.command && (e.command.name == prev.command.name);
18162
+ if (e.command.name == "insertstring") {
18163
+ var text = e.args;
18164
+ if (this.mergeNextCommand === undefined)
18165
+ this.mergeNextCommand = true;
18166
+
18167
+ shouldMerge = shouldMerge
18168
+ && this.mergeNextCommand // previous command allows to coalesce with
18169
+ && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type
18170
+
18171
+ this.mergeNextCommand = true;
18172
+ } else {
18173
+ shouldMerge = shouldMerge
18174
+ && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable
18175
+ }
18176
+
18177
+ if (
18178
+ this.$mergeUndoDeltas != "always"
18179
+ && Date.now() - this.sequenceStartTime > 2000
18180
+ ) {
18181
+ shouldMerge = false; // the sequence is too long
18182
+ }
18183
+
18184
+ if (shouldMerge)
18185
+ this.session.mergeUndoDeltas = true;
18186
+ else if (mergeableCommands.indexOf(e.command.name) !== -1)
18187
+ this.sequenceStartTime = Date.now();
18188
+ };
18189
+ this.setKeyboardHandler = function(keyboardHandler, cb) {
18190
+ if (keyboardHandler && typeof keyboardHandler === "string") {
18191
+ this.$keybindingId = keyboardHandler;
18192
+ var _self = this;
18193
+ config.loadModule(["keybinding", keyboardHandler], function(module) {
18194
+ if (_self.$keybindingId == keyboardHandler)
18195
+ _self.keyBinding.setKeyboardHandler(module && module.handler);
18196
+ cb && cb();
18197
+ });
18198
+ } else {
18199
+ this.$keybindingId = null;
18200
+ this.keyBinding.setKeyboardHandler(keyboardHandler);
18201
+ cb && cb();
18202
+ }
18203
+ };
18204
+ this.getKeyboardHandler = function() {
18205
+ return this.keyBinding.getKeyboardHandler();
18206
+ };
18207
+ this.setSession = function(session) {
18208
+ if (this.session == session)
18209
+ return;
18210
+
18211
+ var oldSession = this.session;
18212
+ if (oldSession) {
18213
+ this.session.removeEventListener("change", this.$onDocumentChange);
18214
+ this.session.removeEventListener("changeMode", this.$onChangeMode);
18215
+ this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
18216
+ this.session.removeEventListener("changeTabSize", this.$onChangeTabSize);
18217
+ this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit);
18218
+ this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode);
18219
+ this.session.removeEventListener("onChangeFold", this.$onChangeFold);
18220
+ this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker);
18221
+ this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker);
18222
+ this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint);
18223
+ this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation);
18224
+ this.session.removeEventListener("changeOverwrite", this.$onCursorChange);
18225
+ this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange);
18226
+ this.session.removeEventListener("changeScrollLeft", this.$onScrollLeftChange);
18227
+
18228
+ var selection = this.session.getSelection();
18229
+ selection.removeEventListener("changeCursor", this.$onCursorChange);
18230
+ selection.removeEventListener("changeSelection", this.$onSelectionChange);
18231
+ }
18232
+
18233
+ this.session = session;
18234
+ if (session) {
18235
+ this.$onDocumentChange = this.onDocumentChange.bind(this);
18236
+ session.addEventListener("change", this.$onDocumentChange);
18237
+ this.renderer.setSession(session);
18238
+
18239
+ this.$onChangeMode = this.onChangeMode.bind(this);
18240
+ session.addEventListener("changeMode", this.$onChangeMode);
18241
+
18242
+ this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
18243
+ session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
18244
+
18245
+ this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
18246
+ session.addEventListener("changeTabSize", this.$onChangeTabSize);
18247
+
18248
+ this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
18249
+ session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
18250
+
18251
+ this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
18252
+ session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
18253
+
18254
+ this.$onChangeFold = this.onChangeFold.bind(this);
18255
+ session.addEventListener("changeFold", this.$onChangeFold);
18256
+
18257
+ this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
18258
+ this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
18259
+
18260
+ this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
18261
+ this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
18262
+
18263
+ this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
18264
+ this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
18265
+
18266
+ this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
18267
+ this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
18268
+
18269
+ this.$onCursorChange = this.onCursorChange.bind(this);
18270
+ this.session.addEventListener("changeOverwrite", this.$onCursorChange);
18271
+
18272
+ this.$onScrollTopChange = this.onScrollTopChange.bind(this);
18273
+ this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
18274
+
18275
+ this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
18276
+ this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
18277
+
18278
+ this.selection = session.getSelection();
18279
+ this.selection.addEventListener("changeCursor", this.$onCursorChange);
18280
+
18281
+ this.$onSelectionChange = this.onSelectionChange.bind(this);
18282
+ this.selection.addEventListener("changeSelection", this.$onSelectionChange);
18283
+
18284
+ this.onChangeMode();
18285
+
18286
+ this.$blockScrolling += 1;
18287
+ this.onCursorChange();
18288
+ this.$blockScrolling -= 1;
18289
+
18290
+ this.onScrollTopChange();
18291
+ this.onScrollLeftChange();
18292
+ this.onSelectionChange();
18293
+ this.onChangeFrontMarker();
18294
+ this.onChangeBackMarker();
18295
+ this.onChangeBreakpoint();
18296
+ this.onChangeAnnotation();
18297
+ this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
18298
+ this.renderer.updateFull();
18299
+ } else {
18300
+ this.selection = null;
18301
+ this.renderer.setSession(session);
18302
+ }
18303
+
18304
+ this._signal("changeSession", {
18305
+ session: session,
18306
+ oldSession: oldSession
18307
+ });
18308
+
18309
+ oldSession && oldSession._signal("changeEditor", {oldEditor: this});
18310
+ session && session._signal("changeEditor", {editor: this});
18311
+ };
18312
+ this.getSession = function() {
18313
+ return this.session;
18314
+ };
18315
+ this.setValue = function(val, cursorPos) {
18316
+ this.session.doc.setValue(val);
18317
+
18318
+ if (!cursorPos)
18319
+ this.selectAll();
18320
+ else if (cursorPos == 1)
18321
+ this.navigateFileEnd();
18322
+ else if (cursorPos == -1)
18323
+ this.navigateFileStart();
18324
+
18325
+ return val;
18326
+ };
18327
+ this.getValue = function() {
18328
+ return this.session.getValue();
18329
+ };
18330
+ this.getSelection = function() {
18331
+ return this.selection;
18332
+ };
18333
+ this.resize = function(force) {
18334
+ this.renderer.onResize(force);
18335
+ };
18336
+ this.setTheme = function(theme, cb) {
18337
+ this.renderer.setTheme(theme, cb);
18338
+ };
18339
+ this.getTheme = function() {
18340
+ return this.renderer.getTheme();
18341
+ };
18342
+ this.setStyle = function(style) {
18343
+ this.renderer.setStyle(style);
18344
+ };
18345
+ this.unsetStyle = function(style) {
18346
+ this.renderer.unsetStyle(style);
18347
+ };
18348
+ this.getFontSize = function () {
18349
+ return this.getOption("fontSize") ||
18350
+ dom.computedStyle(this.container, "fontSize");
18351
+ };
18352
+ this.setFontSize = function(size) {
18353
+ this.setOption("fontSize", size);
18354
+ };
18355
+
18356
+ this.$highlightBrackets = function() {
18357
+ if (this.session.$bracketHighlight) {
18358
+ this.session.removeMarker(this.session.$bracketHighlight);
18359
+ this.session.$bracketHighlight = null;
18360
+ }
18361
+
18362
+ if (this.$highlightPending) {
18363
+ return;
18364
+ }
18365
+ var self = this;
18366
+ this.$highlightPending = true;
18367
+ setTimeout(function() {
18368
+ self.$highlightPending = false;
18369
+ var session = self.session;
18370
+ if (!session || !session.bgTokenizer) return;
18371
+ var pos = session.findMatchingBracket(self.getCursorPosition());
18372
+ if (pos) {
18373
+ var range = new Range(pos.row, pos.column, pos.row, pos.column + 1);
18374
+ } else if (session.$mode.getMatching) {
18375
+ var range = session.$mode.getMatching(self.session);
18376
+ }
18377
+ if (range)
18378
+ session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text");
18379
+ }, 50);
18380
+ };
18381
+ this.$highlightTags = function() {
18382
+ if (this.$highlightTagPending)
18383
+ return;
18384
+ var self = this;
18385
+ this.$highlightTagPending = true;
18386
+ setTimeout(function() {
18387
+ self.$highlightTagPending = false;
18388
+
18389
+ var session = self.session;
18390
+ if (!session || !session.bgTokenizer) return;
18391
+
18392
+ var pos = self.getCursorPosition();
18393
+ var iterator = new TokenIterator(self.session, pos.row, pos.column);
18394
+ var token = iterator.getCurrentToken();
18395
+
18396
+ if (!token || token.type.indexOf('tag-name') === -1) {
18397
+ session.removeMarker(session.$tagHighlight);
18398
+ session.$tagHighlight = null;
18399
+ return;
18400
+ }
18401
+
18402
+ var tag = token.value;
18403
+ var depth = 0;
18404
+ var prevToken = iterator.stepBackward();
18405
+
18406
+ if (prevToken.value == '<'){
18407
+ do {
18408
+ prevToken = token;
18409
+ token = iterator.stepForward();
18410
+
18411
+ if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {
18412
+ if (prevToken.value === '<'){
18413
+ depth++;
18414
+ } else if (prevToken.value === '</'){
18415
+ depth--;
18416
+ }
18417
+ }
18418
+
18419
+ } while (token && depth >= 0);
18420
+ } else {
18421
+ do {
18422
+ token = prevToken;
18423
+ prevToken = iterator.stepBackward();
18424
+
18425
+ if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {
18426
+ if (prevToken.value === '<') {
18427
+ depth++;
18428
+ } else if (prevToken.value === '</') {
18429
+ depth--;
18430
+ }
18431
+ }
18432
+ } while (prevToken && depth <= 0);
18433
+ iterator.stepForward();
18434
+ }
18435
+
18436
+ if (!token) {
18437
+ session.removeMarker(session.$tagHighlight);
18438
+ session.$tagHighlight = null;
18439
+ return;
18440
+ }
18441
+
18442
+ var row = iterator.getCurrentTokenRow();
18443
+ var column = iterator.getCurrentTokenColumn();
18444
+ var range = new Range(row, column, row, column+token.value.length);
18445
+ if (session.$tagHighlight && range.compareRange(session.$backMarkers[session.$tagHighlight].range)!==0) {
18446
+ session.removeMarker(session.$tagHighlight);
18447
+ session.$tagHighlight = null;
18448
+ }
18449
+
18450
+ if (range && !session.$tagHighlight)
18451
+ session.$tagHighlight = session.addMarker(range, "ace_bracket", "text");
18452
+ }, 50);
18453
+ };
18454
+ this.focus = function() {
18455
+ var _self = this;
18456
+ setTimeout(function() {
18457
+ _self.textInput.focus();
18458
+ });
18459
+ this.textInput.focus();
18460
+ };
18461
+ this.isFocused = function() {
18462
+ return this.textInput.isFocused();
18463
+ };
18464
+ this.blur = function() {
18465
+ this.textInput.blur();
18466
+ };
18467
+ this.onFocus = function(e) {
18468
+ if (this.$isFocused)
18469
+ return;
18470
+ this.$isFocused = true;
18471
+ this.renderer.showCursor();
18472
+ this.renderer.visualizeFocus();
18473
+ this._emit("focus", e);
18474
+ };
18475
+ this.onBlur = function(e) {
18476
+ if (!this.$isFocused)
18477
+ return;
18478
+ this.$isFocused = false;
18479
+ this.renderer.hideCursor();
18480
+ this.renderer.visualizeBlur();
18481
+ this._emit("blur", e);
18482
+ };
18483
+
18484
+ this.$cursorChange = function() {
18485
+ this.renderer.updateCursor();
18486
+ };
18487
+ this.onDocumentChange = function(e) {
18488
+ var delta = e.data;
18489
+ var range = delta.range;
18490
+ var lastRow;
18491
+
18492
+ if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
18493
+ lastRow = range.end.row;
18494
+ else
18495
+ lastRow = Infinity;
18496
+ this.renderer.updateLines(range.start.row, lastRow, this.session.$useWrapMode);
18497
+
18498
+ this._signal("change", e);
18499
+ this.$cursorChange();
18500
+ this.$updateHighlightActiveLine();
18501
+ };
18502
+
18503
+ this.onTokenizerUpdate = function(e) {
18504
+ var rows = e.data;
18505
+ this.renderer.updateLines(rows.first, rows.last);
18506
+ };
18507
+
18508
+
18509
+ this.onScrollTopChange = function() {
18510
+ this.renderer.scrollToY(this.session.getScrollTop());
18511
+ };
18512
+
18513
+ this.onScrollLeftChange = function() {
18514
+ this.renderer.scrollToX(this.session.getScrollLeft());
18515
+ };
18516
+ this.onCursorChange = function() {
18517
+ this.$cursorChange();
18518
+
18519
+ if (!this.$blockScrolling) {
18520
+ this.renderer.scrollCursorIntoView();
18521
+ }
18522
+
18523
+ this.$highlightBrackets();
18524
+ this.$highlightTags();
18525
+ this.$updateHighlightActiveLine();
18526
+ this._signal("changeSelection");
18527
+ };
18528
+
18529
+ this.$updateHighlightActiveLine = function() {
18530
+ var session = this.getSession();
18531
+
18532
+ var highlight;
18533
+ if (this.$highlightActiveLine) {
18534
+ if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
18535
+ highlight = this.getCursorPosition();
18536
+ if (this.renderer.$maxLines && this.session.getLength() === 1 && !(this.renderer.$minLines > 1))
18537
+ highlight = false;
18538
+ }
18539
+
18540
+ if (session.$highlightLineMarker && !highlight) {
18541
+ session.removeMarker(session.$highlightLineMarker.id);
18542
+ session.$highlightLineMarker = null;
18543
+ } else if (!session.$highlightLineMarker && highlight) {
18544
+ var range = new Range(highlight.row, highlight.column, highlight.row, Infinity);
18545
+ range.id = session.addMarker(range, "ace_active-line", "screenLine");
18546
+ session.$highlightLineMarker = range;
18547
+ } else if (highlight) {
18548
+ session.$highlightLineMarker.start.row = highlight.row;
18549
+ session.$highlightLineMarker.end.row = highlight.row;
18550
+ session.$highlightLineMarker.start.column = highlight.column;
18551
+ session._signal("changeBackMarker");
18552
+ }
18553
+ };
18554
+
18555
+ this.onSelectionChange = function(e) {
18556
+ var session = this.session;
18557
+
18558
+ if (session.$selectionMarker) {
18559
+ session.removeMarker(session.$selectionMarker);
18560
+ }
18561
+ session.$selectionMarker = null;
18562
+
18563
+ if (!this.selection.isEmpty()) {
18564
+ var range = this.selection.getRange();
18565
+ var style = this.getSelectionStyle();
18566
+ session.$selectionMarker = session.addMarker(range, "ace_selection", style);
18567
+ } else {
18568
+ this.$updateHighlightActiveLine();
18569
+ }
18570
+
18571
+ var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp();
18572
+ this.session.highlight(re);
18573
+
18574
+ this._signal("changeSelection");
18575
+ };
18576
+
18577
+ this.$getSelectionHighLightRegexp = function() {
18578
+ var session = this.session;
18579
+
18580
+ var selection = this.getSelectionRange();
18581
+ if (selection.isEmpty() || selection.isMultiLine())
18582
+ return;
18583
+
18584
+ var startOuter = selection.start.column - 1;
18585
+ var endOuter = selection.end.column + 1;
18586
+ var line = session.getLine(selection.start.row);
18587
+ var lineCols = line.length;
18588
+ var needle = line.substring(Math.max(startOuter, 0),
18589
+ Math.min(endOuter, lineCols));
18590
+ if ((startOuter >= 0 && /^[\w\d]/.test(needle)) ||
18591
+ (endOuter <= lineCols && /[\w\d]$/.test(needle)))
18592
+ return;
18593
+
18594
+ needle = line.substring(selection.start.column, selection.end.column);
18595
+ if (!/^[\w\d]+$/.test(needle))
18596
+ return;
18597
+
18598
+ var re = this.$search.$assembleRegExp({
18599
+ wholeWord: true,
18600
+ caseSensitive: true,
18601
+ needle: needle
18602
+ });
18603
+
18604
+ return re;
18605
+ };
18606
+
18607
+
18608
+ this.onChangeFrontMarker = function() {
18609
+ this.renderer.updateFrontMarkers();
18610
+ };
18611
+
18612
+ this.onChangeBackMarker = function() {
18613
+ this.renderer.updateBackMarkers();
18614
+ };
18615
+
18616
+
18617
+ this.onChangeBreakpoint = function() {
18618
+ this.renderer.updateBreakpoints();
18619
+ };
18620
+
18621
+ this.onChangeAnnotation = function() {
18622
+ this.renderer.setAnnotations(this.session.getAnnotations());
18623
+ };
18624
+
18625
+
18626
+ this.onChangeMode = function(e) {
18627
+ this.renderer.updateText();
18628
+ this._emit("changeMode", e);
18629
+ };
18630
+
18631
+
18632
+ this.onChangeWrapLimit = function() {
18633
+ this.renderer.updateFull();
18634
+ };
18635
+
18636
+ this.onChangeWrapMode = function() {
18637
+ this.renderer.onResize(true);
18638
+ };
18639
+
18640
+
18641
+ this.onChangeFold = function() {
18642
+ this.$updateHighlightActiveLine();
18643
+ this.renderer.updateFull();
18644
+ };
18645
+ this.getSelectedText = function() {
18646
+ return this.session.getTextRange(this.getSelectionRange());
18647
+ };
18648
+ this.getCopyText = function() {
18649
+ var text = this.getSelectedText();
18650
+ this._signal("copy", text);
18651
+ return text;
18652
+ };
18653
+ this.onCopy = function() {
18654
+ this.commands.exec("copy", this);
18655
+ };
18656
+ this.onCut = function() {
18657
+ this.commands.exec("cut", this);
18658
+ };
18659
+ this.onPaste = function(text) {
18660
+ if (this.$readOnly)
18661
+ return;
18662
+ var e = {text: text};
18663
+ this._signal("paste", e);
18664
+ this.insert(e.text, true);
18665
+ };
18666
+
18667
+ this.execCommand = function(command, args) {
18668
+ return this.commands.exec(command, this, args);
18669
+ };
18670
+ this.insert = function(text, pasted) {
18671
+ var session = this.session;
18672
+ var mode = session.getMode();
18673
+ var cursor = this.getCursorPosition();
18674
+
18675
+ if (this.getBehavioursEnabled() && !pasted) {
18676
+ var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
18677
+ if (transform) {
18678
+ if (text !== transform.text) {
18679
+ this.session.mergeUndoDeltas = false;
18680
+ this.$mergeNextCommand = false;
18681
+ }
18682
+ text = transform.text;
18683
+
18684
+ }
18685
+ }
18686
+
18687
+ if (text == "\t")
18688
+ text = this.session.getTabString();
18689
+ if (!this.selection.isEmpty()) {
18690
+ var range = this.getSelectionRange();
18691
+ cursor = this.session.remove(range);
18692
+ this.clearSelection();
18693
+ }
18694
+ else if (this.session.getOverwrite()) {
18695
+ var range = new Range.fromPoints(cursor, cursor);
18696
+ range.end.column += text.length;
18697
+ this.session.remove(range);
18698
+ }
18699
+
18700
+ if (text == "\n" || text == "\r\n") {
18701
+ var line = session.getLine(cursor.row);
18702
+ if (cursor.column > line.search(/\S|$/)) {
18703
+ var d = line.substr(cursor.column).search(/\S|$/);
18704
+ session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d);
18705
+ }
18706
+ }
18707
+ this.clearSelection();
18708
+
18709
+ var start = cursor.column;
18710
+ var lineState = session.getState(cursor.row);
18711
+ var line = session.getLine(cursor.row);
18712
+ var shouldOutdent = mode.checkOutdent(lineState, line, text);
18713
+ var end = session.insert(cursor, text);
18714
+
18715
+ if (transform && transform.selection) {
18716
+ if (transform.selection.length == 2) { // Transform relative to the current column
18717
+ this.selection.setSelectionRange(
18718
+ new Range(cursor.row, start + transform.selection[0],
18719
+ cursor.row, start + transform.selection[1]));
18720
+ } else { // Transform relative to the current row.
18721
+ this.selection.setSelectionRange(
18722
+ new Range(cursor.row + transform.selection[0],
18723
+ transform.selection[1],
18724
+ cursor.row + transform.selection[2],
18725
+ transform.selection[3]));
18726
+ }
18727
+ }
18728
+
18729
+ if (session.getDocument().isNewLine(text)) {
18730
+ var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
18731
+
18732
+ session.insert({row: cursor.row+1, column: 0}, lineIndent);
18733
+ }
18734
+ if (shouldOutdent)
18735
+ mode.autoOutdent(lineState, session, cursor.row);
18736
+ };
18737
+
18738
+ this.onTextInput = function(text) {
18739
+ this.keyBinding.onTextInput(text);
18740
+ };
18741
+
18742
+ this.onCommandKey = function(e, hashId, keyCode) {
18743
+ this.keyBinding.onCommandKey(e, hashId, keyCode);
18744
+ };
18745
+ this.setOverwrite = function(overwrite) {
18746
+ this.session.setOverwrite(overwrite);
18747
+ };
18748
+ this.getOverwrite = function() {
18749
+ return this.session.getOverwrite();
18750
+ };
18751
+ this.toggleOverwrite = function() {
18752
+ this.session.toggleOverwrite();
18753
+ };
18754
+ this.setScrollSpeed = function(speed) {
18755
+ this.setOption("scrollSpeed", speed);
18756
+ };
18757
+ this.getScrollSpeed = function() {
18758
+ return this.getOption("scrollSpeed");
18759
+ };
18760
+ this.setDragDelay = function(dragDelay) {
18761
+ this.setOption("dragDelay", dragDelay);
18762
+ };
18763
+ this.getDragDelay = function() {
18764
+ return this.getOption("dragDelay");
18765
+ };
18766
+ this.setSelectionStyle = function(val) {
18767
+ this.setOption("selectionStyle", val);
18768
+ };
18769
+ this.getSelectionStyle = function() {
18770
+ return this.getOption("selectionStyle");
18771
+ };
18772
+ this.setHighlightActiveLine = function(shouldHighlight) {
18773
+ this.setOption("highlightActiveLine", shouldHighlight);
18774
+ };
18775
+ this.getHighlightActiveLine = function() {
18776
+ return this.getOption("highlightActiveLine");
18777
+ };
18778
+ this.setHighlightGutterLine = function(shouldHighlight) {
18779
+ this.setOption("highlightGutterLine", shouldHighlight);
18780
+ };
18781
+
18782
+ this.getHighlightGutterLine = function() {
18783
+ return this.getOption("highlightGutterLine");
18784
+ };
18785
+ this.setHighlightSelectedWord = function(shouldHighlight) {
18786
+ this.setOption("highlightSelectedWord", shouldHighlight);
18787
+ };
18788
+ this.getHighlightSelectedWord = function() {
18789
+ return this.$highlightSelectedWord;
18790
+ };
18791
+
18792
+ this.setAnimatedScroll = function(shouldAnimate){
18793
+ this.renderer.setAnimatedScroll(shouldAnimate);
18794
+ };
18795
+
18796
+ this.getAnimatedScroll = function(){
18797
+ return this.renderer.getAnimatedScroll();
18798
+ };
18799
+ this.setShowInvisibles = function(showInvisibles) {
18800
+ this.renderer.setShowInvisibles(showInvisibles);
18801
+ };
18802
+ this.getShowInvisibles = function() {
18803
+ return this.renderer.getShowInvisibles();
18804
+ };
18805
+
18806
+ this.setDisplayIndentGuides = function(display) {
18807
+ this.renderer.setDisplayIndentGuides(display);
18808
+ };
18809
+
18810
+ this.getDisplayIndentGuides = function() {
18811
+ return this.renderer.getDisplayIndentGuides();
18812
+ };
18813
+ this.setShowPrintMargin = function(showPrintMargin) {
18814
+ this.renderer.setShowPrintMargin(showPrintMargin);
18815
+ };
18816
+ this.getShowPrintMargin = function() {
18817
+ return this.renderer.getShowPrintMargin();
18818
+ };
18819
+ this.setPrintMarginColumn = function(showPrintMargin) {
18820
+ this.renderer.setPrintMarginColumn(showPrintMargin);
18821
+ };
18822
+ this.getPrintMarginColumn = function() {
18823
+ return this.renderer.getPrintMarginColumn();
18824
+ };
18825
+ this.setReadOnly = function(readOnly) {
18826
+ this.setOption("readOnly", readOnly);
18827
+ };
18828
+ this.getReadOnly = function() {
18829
+ return this.getOption("readOnly");
18830
+ };
18831
+ this.setBehavioursEnabled = function (enabled) {
18832
+ this.setOption("behavioursEnabled", enabled);
18833
+ };
18834
+ this.getBehavioursEnabled = function () {
18835
+ return this.getOption("behavioursEnabled");
18836
+ };
18837
+ this.setWrapBehavioursEnabled = function (enabled) {
18838
+ this.setOption("wrapBehavioursEnabled", enabled);
18839
+ };
18840
+ this.getWrapBehavioursEnabled = function () {
18841
+ return this.getOption("wrapBehavioursEnabled");
18842
+ };
18843
+ this.setShowFoldWidgets = function(show) {
18844
+ this.setOption("showFoldWidgets", show);
18845
+
18846
+ };
18847
+ this.getShowFoldWidgets = function() {
18848
+ return this.getOption("showFoldWidgets");
18849
+ };
18850
+
18851
+ this.setFadeFoldWidgets = function(fade) {
18852
+ this.setOption("fadeFoldWidgets", fade);
18853
+ };
18854
+
18855
+ this.getFadeFoldWidgets = function() {
18856
+ return this.getOption("fadeFoldWidgets");
18857
+ };
18858
+ this.remove = function(dir) {
18859
+ if (this.selection.isEmpty()){
18860
+ if (dir == "left")
18861
+ this.selection.selectLeft();
18862
+ else
18863
+ this.selection.selectRight();
18864
+ }
18865
+
18866
+ var range = this.getSelectionRange();
18867
+ if (this.getBehavioursEnabled()) {
18868
+ var session = this.session;
18869
+ var state = session.getState(range.start.row);
18870
+ var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
18871
+
18872
+ if (range.end.column === 0) {
18873
+ var text = session.getTextRange(range);
18874
+ if (text[text.length - 1] == "\n") {
18875
+ var line = session.getLine(range.end.row);
18876
+ if (/^\s+$/.test(line)) {
18877
+ range.end.column = line.length;
18878
+ }
18879
+ }
18880
+ }
18881
+ if (new_range)
18882
+ range = new_range;
18883
+ }
18884
+
18885
+ this.session.remove(range);
18886
+ this.clearSelection();
18887
+ };
18888
+ this.removeWordRight = function() {
18889
+ if (this.selection.isEmpty())
18890
+ this.selection.selectWordRight();
18891
+
18892
+ this.session.remove(this.getSelectionRange());
18893
+ this.clearSelection();
18894
+ };
18895
+ this.removeWordLeft = function() {
18896
+ if (this.selection.isEmpty())
18897
+ this.selection.selectWordLeft();
18898
+
18899
+ this.session.remove(this.getSelectionRange());
18900
+ this.clearSelection();
18901
+ };
18902
+ this.removeToLineStart = function() {
18903
+ if (this.selection.isEmpty())
18904
+ this.selection.selectLineStart();
18905
+
18906
+ this.session.remove(this.getSelectionRange());
18907
+ this.clearSelection();
18908
+ };
18909
+ this.removeToLineEnd = function() {
18910
+ if (this.selection.isEmpty())
18911
+ this.selection.selectLineEnd();
18912
+
18913
+ var range = this.getSelectionRange();
18914
+ if (range.start.column == range.end.column && range.start.row == range.end.row) {
18915
+ range.end.column = 0;
18916
+ range.end.row++;
18917
+ }
18918
+
18919
+ this.session.remove(range);
18920
+ this.clearSelection();
18921
+ };
18922
+ this.splitLine = function() {
18923
+ if (!this.selection.isEmpty()) {
18924
+ this.session.remove(this.getSelectionRange());
18925
+ this.clearSelection();
18926
+ }
18927
+
18928
+ var cursor = this.getCursorPosition();
18929
+ this.insert("\n");
18930
+ this.moveCursorToPosition(cursor);
18931
+ };
18932
+ this.transposeLetters = function() {
18933
+ if (!this.selection.isEmpty()) {
18934
+ return;
18935
+ }
18936
+
18937
+ var cursor = this.getCursorPosition();
18938
+ var column = cursor.column;
18939
+ if (column === 0)
18940
+ return;
18941
+
18942
+ var line = this.session.getLine(cursor.row);
18943
+ var swap, range;
18944
+ if (column < line.length) {
18945
+ swap = line.charAt(column) + line.charAt(column-1);
18946
+ range = new Range(cursor.row, column-1, cursor.row, column+1);
18947
+ }
18948
+ else {
18949
+ swap = line.charAt(column-1) + line.charAt(column-2);
18950
+ range = new Range(cursor.row, column-2, cursor.row, column);
18951
+ }
18952
+ this.session.replace(range, swap);
18953
+ };
18954
+ this.toLowerCase = function() {
18955
+ var originalRange = this.getSelectionRange();
18956
+ if (this.selection.isEmpty()) {
18957
+ this.selection.selectWord();
18958
+ }
18959
+
18960
+ var range = this.getSelectionRange();
18961
+ var text = this.session.getTextRange(range);
18962
+ this.session.replace(range, text.toLowerCase());
18963
+ this.selection.setSelectionRange(originalRange);
18964
+ };
18965
+ this.toUpperCase = function() {
18966
+ var originalRange = this.getSelectionRange();
18967
+ if (this.selection.isEmpty()) {
18968
+ this.selection.selectWord();
18969
+ }
18970
+
18971
+ var range = this.getSelectionRange();
18972
+ var text = this.session.getTextRange(range);
18973
+ this.session.replace(range, text.toUpperCase());
18974
+ this.selection.setSelectionRange(originalRange);
18975
+ };
18976
+ this.indent = function() {
18977
+ var session = this.session;
18978
+ var range = this.getSelectionRange();
18979
+
18980
+ if (range.start.row < range.end.row) {
18981
+ var rows = this.$getSelectedRows();
18982
+ session.indentRows(rows.first, rows.last, "\t");
18983
+ return;
18984
+ } else if (range.start.column < range.end.column) {
18985
+ var text = session.getTextRange(range);
18986
+ if (!/^\s+$/.test(text)) {
18987
+ var rows = this.$getSelectedRows();
18988
+ session.indentRows(rows.first, rows.last, "\t");
18989
+ return;
18990
+ }
18991
+ }
18992
+
18993
+ var line = session.getLine(range.start.row);
18994
+ var position = range.start;
18995
+ var size = session.getTabSize();
18996
+ var column = session.documentToScreenColumn(position.row, position.column);
18997
+
18998
+ if (this.session.getUseSoftTabs()) {
18999
+ var count = (size - column % size);
19000
+ var indentString = lang.stringRepeat(" ", count);
19001
+ } else {
19002
+ var count = column % size;
19003
+ while (line[range.start.column] == " " && count) {
19004
+ range.start.column--;
19005
+ count--;
19006
+ }
19007
+ this.selection.setSelectionRange(range);
19008
+ indentString = "\t";
19009
+ }
19010
+ return this.insert(indentString);
19011
+ };
19012
+ this.blockIndent = function() {
19013
+ var rows = this.$getSelectedRows();
19014
+ this.session.indentRows(rows.first, rows.last, "\t");
19015
+ };
19016
+ this.blockOutdent = function() {
19017
+ var selection = this.session.getSelection();
19018
+ this.session.outdentRows(selection.getRange());
19019
+ };
19020
+ this.sortLines = function() {
19021
+ var rows = this.$getSelectedRows();
19022
+ var session = this.session;
19023
+
19024
+ var lines = [];
19025
+ for (i = rows.first; i <= rows.last; i++)
19026
+ lines.push(session.getLine(i));
19027
+
19028
+ lines.sort(function(a, b) {
19029
+ if (a.toLowerCase() < b.toLowerCase()) return -1;
19030
+ if (a.toLowerCase() > b.toLowerCase()) return 1;
19031
+ return 0;
19032
+ });
19033
+
19034
+ var deleteRange = new Range(0, 0, 0, 0);
19035
+ for (var i = rows.first; i <= rows.last; i++) {
19036
+ var line = session.getLine(i);
19037
+ deleteRange.start.row = i;
19038
+ deleteRange.end.row = i;
19039
+ deleteRange.end.column = line.length;
19040
+ session.replace(deleteRange, lines[i-rows.first]);
19041
+ }
19042
+ };
19043
+ this.toggleCommentLines = function() {
19044
+ var state = this.session.getState(this.getCursorPosition().row);
19045
+ var rows = this.$getSelectedRows();
19046
+ this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
19047
+ };
19048
+
19049
+ this.toggleBlockComment = function() {
19050
+ var cursor = this.getCursorPosition();
19051
+ var state = this.session.getState(cursor.row);
19052
+ var range = this.getSelectionRange();
19053
+ this.session.getMode().toggleBlockComment(state, this.session, range, cursor);
19054
+ };
19055
+ this.getNumberAt = function(row, column) {
19056
+ var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g;
19057
+ _numberRx.lastIndex = 0;
19058
+
19059
+ var s = this.session.getLine(row);
19060
+ while (_numberRx.lastIndex < column) {
19061
+ var m = _numberRx.exec(s);
19062
+ if(m.index <= column && m.index+m[0].length >= column){
19063
+ var number = {
19064
+ value: m[0],
19065
+ start: m.index,
19066
+ end: m.index+m[0].length
19067
+ };
19068
+ return number;
19069
+ }
19070
+ }
19071
+ return null;
19072
+ };
19073
+ this.modifyNumber = function(amount) {
19074
+ var row = this.selection.getCursor().row;
19075
+ var column = this.selection.getCursor().column;
19076
+ var charRange = new Range(row, column-1, row, column);
19077
+
19078
+ var c = this.session.getTextRange(charRange);
19079
+ if (!isNaN(parseFloat(c)) && isFinite(c)) {
19080
+ var nr = this.getNumberAt(row, column);
19081
+ if (nr) {
19082
+ var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end;
19083
+ var decimals = nr.start + nr.value.length - fp;
19084
+
19085
+ var t = parseFloat(nr.value);
19086
+ t *= Math.pow(10, decimals);
19087
+
19088
+
19089
+ if(fp !== nr.end && column < fp){
19090
+ amount *= Math.pow(10, nr.end - column - 1);
19091
+ } else {
19092
+ amount *= Math.pow(10, nr.end - column);
19093
+ }
19094
+
19095
+ t += amount;
19096
+ t /= Math.pow(10, decimals);
19097
+ var nnr = t.toFixed(decimals);
19098
+ var replaceRange = new Range(row, nr.start, row, nr.end);
19099
+ this.session.replace(replaceRange, nnr);
19100
+ this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length));
19101
+
19102
+ }
19103
+ }
19104
+ };
19105
+ this.removeLines = function() {
19106
+ var rows = this.$getSelectedRows();
19107
+ var range;
19108
+ if (rows.first === 0 || rows.last+1 < this.session.getLength())
19109
+ range = new Range(rows.first, 0, rows.last+1, 0);
19110
+ else
19111
+ range = new Range(
19112
+ rows.first-1, this.session.getLine(rows.first-1).length,
19113
+ rows.last, this.session.getLine(rows.last).length
19114
+ );
19115
+ this.session.remove(range);
19116
+ this.clearSelection();
19117
+ };
19118
+
19119
+ this.duplicateSelection = function() {
19120
+ var sel = this.selection;
19121
+ var doc = this.session;
19122
+ var range = sel.getRange();
19123
+ var reverse = sel.isBackwards();
19124
+ if (range.isEmpty()) {
19125
+ var row = range.start.row;
19126
+ doc.duplicateLines(row, row);
19127
+ } else {
19128
+ var point = reverse ? range.start : range.end;
19129
+ var endPoint = doc.insert(point, doc.getTextRange(range), false);
19130
+ range.start = point;
19131
+ range.end = endPoint;
19132
+
19133
+ sel.setSelectionRange(range, reverse);
19134
+ }
19135
+ };
19136
+ this.moveLinesDown = function() {
19137
+ this.$moveLines(function(firstRow, lastRow) {
19138
+ return this.session.moveLinesDown(firstRow, lastRow);
19139
+ });
19140
+ };
19141
+ this.moveLinesUp = function() {
19142
+ this.$moveLines(function(firstRow, lastRow) {
19143
+ return this.session.moveLinesUp(firstRow, lastRow);
19144
+ });
19145
+ };
19146
+ this.moveText = function(range, toPosition, copy) {
19147
+ return this.session.moveText(range, toPosition, copy);
19148
+ };
19149
+ this.copyLinesUp = function() {
19150
+ this.$moveLines(function(firstRow, lastRow) {
19151
+ this.session.duplicateLines(firstRow, lastRow);
19152
+ return 0;
19153
+ });
19154
+ };
19155
+ this.copyLinesDown = function() {
19156
+ this.$moveLines(function(firstRow, lastRow) {
19157
+ return this.session.duplicateLines(firstRow, lastRow);
19158
+ });
19159
+ };
19160
+ this.$moveLines = function(mover) {
19161
+ var selection = this.selection;
19162
+ if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {
19163
+ var range = selection.toOrientedRange();
19164
+ var rows = this.$getSelectedRows(range);
19165
+ var linesMoved = mover.call(this, rows.first, rows.last);
19166
+ range.moveBy(linesMoved, 0);
19167
+ selection.fromOrientedRange(range);
19168
+ } else {
19169
+ var ranges = selection.rangeList.ranges;
19170
+ selection.rangeList.detach(this.session);
19171
+
19172
+ for (var i = ranges.length; i--; ) {
19173
+ var rangeIndex = i;
19174
+ var rows = ranges[i].collapseRows();
19175
+ var last = rows.end.row;
19176
+ var first = rows.start.row;
19177
+ while (i--) {
19178
+ rows = ranges[i].collapseRows();
19179
+ if (first - rows.end.row <= 1)
19180
+ first = rows.end.row;
19181
+ else
19182
+ break;
19183
+ }
19184
+ i++;
19185
+
19186
+ var linesMoved = mover.call(this, first, last);
19187
+ while (rangeIndex >= i) {
19188
+ ranges[rangeIndex].moveBy(linesMoved, 0);
19189
+ rangeIndex--;
19190
+ }
19191
+ }
19192
+ selection.fromOrientedRange(selection.ranges[0]);
19193
+ selection.rangeList.attach(this.session);
19194
+ }
19195
+ };
19196
+ this.$getSelectedRows = function() {
19197
+ var range = this.getSelectionRange().collapseRows();
19198
+
19199
+ return {
19200
+ first: this.session.getRowFoldStart(range.start.row),
19201
+ last: this.session.getRowFoldEnd(range.end.row)
19202
+ };
19203
+ };
19204
+
19205
+ this.onCompositionStart = function(text) {
19206
+ this.renderer.showComposition(this.getCursorPosition());
19207
+ };
19208
+
19209
+ this.onCompositionUpdate = function(text) {
19210
+ this.renderer.setCompositionText(text);
19211
+ };
19212
+
19213
+ this.onCompositionEnd = function() {
19214
+ this.renderer.hideComposition();
19215
+ };
19216
+ this.getFirstVisibleRow = function() {
19217
+ return this.renderer.getFirstVisibleRow();
19218
+ };
19219
+ this.getLastVisibleRow = function() {
19220
+ return this.renderer.getLastVisibleRow();
19221
+ };
19222
+ this.isRowVisible = function(row) {
19223
+ return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
19224
+ };
19225
+ this.isRowFullyVisible = function(row) {
19226
+ return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());
19227
+ };
19228
+ this.$getVisibleRowCount = function() {
19229
+ return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;
19230
+ };
19231
+
19232
+ this.$moveByPage = function(dir, select) {
19233
+ var renderer = this.renderer;
19234
+ var config = this.renderer.layerConfig;
19235
+ var rows = dir * Math.floor(config.height / config.lineHeight);
19236
+
19237
+ this.$blockScrolling++;
19238
+ if (select === true) {
19239
+ this.selection.$moveSelection(function(){
19240
+ this.moveCursorBy(rows, 0);
19241
+ });
19242
+ } else if (select === false) {
19243
+ this.selection.moveCursorBy(rows, 0);
19244
+ this.selection.clearSelection();
19245
+ }
19246
+ this.$blockScrolling--;
19247
+
19248
+ var scrollTop = renderer.scrollTop;
19249
+
19250
+ renderer.scrollBy(0, rows * config.lineHeight);
19251
+ if (select != null)
19252
+ renderer.scrollCursorIntoView(null, 0.5);
19253
+
19254
+ renderer.animateScrolling(scrollTop);
19255
+ };
19256
+ this.selectPageDown = function() {
19257
+ this.$moveByPage(1, true);
19258
+ };
19259
+ this.selectPageUp = function() {
19260
+ this.$moveByPage(-1, true);
19261
+ };
19262
+ this.gotoPageDown = function() {
19263
+ this.$moveByPage(1, false);
19264
+ };
19265
+ this.gotoPageUp = function() {
19266
+ this.$moveByPage(-1, false);
19267
+ };
19268
+ this.scrollPageDown = function() {
19269
+ this.$moveByPage(1);
19270
+ };
19271
+ this.scrollPageUp = function() {
19272
+ this.$moveByPage(-1);
19273
+ };
19274
+ this.scrollToRow = function(row) {
19275
+ this.renderer.scrollToRow(row);
19276
+ };
19277
+ this.scrollToLine = function(line, center, animate, callback) {
19278
+ this.renderer.scrollToLine(line, center, animate, callback);
19279
+ };
19280
+ this.centerSelection = function() {
19281
+ var range = this.getSelectionRange();
19282
+ var pos = {
19283
+ row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),
19284
+ column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)
19285
+ };
19286
+ this.renderer.alignCursor(pos, 0.5);
19287
+ };
19288
+ this.getCursorPosition = function() {
19289
+ return this.selection.getCursor();
19290
+ };
19291
+ this.getCursorPositionScreen = function() {
19292
+ return this.session.documentToScreenPosition(this.getCursorPosition());
19293
+ };
19294
+ this.getSelectionRange = function() {
19295
+ return this.selection.getRange();
19296
+ };
19297
+ this.selectAll = function() {
19298
+ this.$blockScrolling += 1;
19299
+ this.selection.selectAll();
19300
+ this.$blockScrolling -= 1;
19301
+ };
19302
+ this.clearSelection = function() {
19303
+ this.selection.clearSelection();
19304
+ };
19305
+ this.moveCursorTo = function(row, column) {
19306
+ this.selection.moveCursorTo(row, column);
19307
+ };
19308
+ this.moveCursorToPosition = function(pos) {
19309
+ this.selection.moveCursorToPosition(pos);
19310
+ };
19311
+ this.jumpToMatching = function(select, expand) {
19312
+ var cursor = this.getCursorPosition();
19313
+ var iterator = new TokenIterator(this.session, cursor.row, cursor.column);
19314
+ var prevToken = iterator.getCurrentToken();
19315
+ var token = prevToken || iterator.stepForward();
19316
+
19317
+ if (!token) return;
19318
+ var matchType;
19319
+ var found = false;
19320
+ var depth = {};
19321
+ var i = cursor.column - token.start;
19322
+ var bracketType;
19323
+ var brackets = {
19324
+ ")": "(",
19325
+ "(": "(",
19326
+ "]": "[",
19327
+ "[": "[",
19328
+ "{": "{",
19329
+ "}": "{"
19330
+ };
19331
+
19332
+ do {
19333
+ if (token.value.match(/[{}()\[\]]/g)) {
19334
+ for (; i < token.value.length && !found; i++) {
19335
+ if (!brackets[token.value[i]]) {
19336
+ continue;
19337
+ }
19338
+
19339
+ bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen");
19340
+
19341
+ if (isNaN(depth[bracketType])) {
19342
+ depth[bracketType] = 0;
19343
+ }
19344
+
19345
+ switch (token.value[i]) {
19346
+ case '(':
19347
+ case '[':
19348
+ case '{':
19349
+ depth[bracketType]++;
19350
+ break;
19351
+ case ')':
19352
+ case ']':
19353
+ case '}':
19354
+ depth[bracketType]--;
19355
+
19356
+ if (depth[bracketType] === -1) {
19357
+ matchType = 'bracket';
19358
+ found = true;
19359
+ }
19360
+ break;
19361
+ }
19362
+ }
19363
+ }
19364
+ else if (token && token.type.indexOf('tag-name') !== -1) {
19365
+ if (isNaN(depth[token.value])) {
19366
+ depth[token.value] = 0;
19367
+ }
19368
+
19369
+ if (prevToken.value === '<') {
19370
+ depth[token.value]++;
19371
+ }
19372
+ else if (prevToken.value === '</') {
19373
+ depth[token.value]--;
19374
+ }
19375
+
19376
+ if (depth[token.value] === -1) {
19377
+ matchType = 'tag';
19378
+ found = true;
19379
+ }
19380
+ }
19381
+
19382
+ if (!found) {
19383
+ prevToken = token;
19384
+ token = iterator.stepForward();
19385
+ i = 0;
19386
+ }
19387
+ } while (token && !found);
19388
+ if (!matchType)
19389
+ return;
19390
+
19391
+ var range, pos;
19392
+ if (matchType === 'bracket') {
19393
+ range = this.session.getBracketRange(cursor);
19394
+ if (!range) {
19395
+ range = new Range(
19396
+ iterator.getCurrentTokenRow(),
19397
+ iterator.getCurrentTokenColumn() + i - 1,
19398
+ iterator.getCurrentTokenRow(),
19399
+ iterator.getCurrentTokenColumn() + i - 1
19400
+ );
19401
+ pos = range.start;
19402
+ if (expand || pos.row === cursor.row && Math.abs(pos.column - cursor.column) < 2)
19403
+ range = this.session.getBracketRange(pos);
19404
+ }
19405
+ }
19406
+ else if (matchType === 'tag') {
19407
+ if (token && token.type.indexOf('tag-name') !== -1)
19408
+ var tag = token.value;
19409
+ else
19410
+ return;
19411
+
19412
+ range = new Range(
19413
+ iterator.getCurrentTokenRow(),
19414
+ iterator.getCurrentTokenColumn() - 2,
19415
+ iterator.getCurrentTokenRow(),
19416
+ iterator.getCurrentTokenColumn() - 2
19417
+ );
19418
+ if (range.compare(cursor.row, cursor.column) === 0) {
19419
+ found = false;
19420
+ do {
19421
+ token = prevToken;
19422
+ prevToken = iterator.stepBackward();
19423
+
19424
+ if (prevToken) {
19425
+ if (prevToken.type.indexOf('tag-close') !== -1) {
19426
+ range.setEnd(iterator.getCurrentTokenRow(), iterator.getCurrentTokenColumn() + 1);
19427
+ }
19428
+
19429
+ if (token.value === tag && token.type.indexOf('tag-name') !== -1) {
19430
+ if (prevToken.value === '<') {
19431
+ depth[tag]++;
19432
+ }
19433
+ else if (prevToken.value === '</') {
19434
+ depth[tag]--;
19435
+ }
19436
+
19437
+ if (depth[tag] === 0)
19438
+ found = true;
19439
+ }
19440
+ }
19441
+ } while (prevToken && !found);
19442
+ }
19443
+ if (token && token.type.indexOf('tag-name')) {
19444
+ pos = range.start;
19445
+ if (pos.row == cursor.row && Math.abs(pos.column - cursor.column) < 2)
19446
+ pos = range.end;
19447
+ }
19448
+ }
19449
+
19450
+ pos = range && range.cursor || pos;
19451
+ if (pos) {
19452
+ if (select) {
19453
+ if (range && expand) {
19454
+ this.selection.setRange(range);
19455
+ } else if (range && range.isEqual(this.getSelectionRange())) {
19456
+ this.clearSelection();
19457
+ } else {
19458
+ this.selection.selectTo(pos.row, pos.column);
19459
+ }
19460
+ } else {
19461
+ this.selection.moveTo(pos.row, pos.column);
19462
+ }
19463
+ }
19464
+ };
19465
+ this.gotoLine = function(lineNumber, column, animate) {
19466
+ this.selection.clearSelection();
19467
+ this.session.unfold({row: lineNumber - 1, column: column || 0});
19468
+
19469
+ this.$blockScrolling += 1;
19470
+ this.exitMultiSelectMode && this.exitMultiSelectMode();
19471
+ this.moveCursorTo(lineNumber - 1, column || 0);
19472
+ this.$blockScrolling -= 1;
19473
+
19474
+ if (!this.isRowFullyVisible(lineNumber - 1))
19475
+ this.scrollToLine(lineNumber - 1, true, animate);
19476
+ };
19477
+ this.navigateTo = function(row, column) {
19478
+ this.selection.moveTo(row, column);
19479
+ };
19480
+ this.navigateUp = function(times) {
19481
+ if (this.selection.isMultiLine() && !this.selection.isBackwards()) {
19482
+ var selectionStart = this.selection.anchor.getPosition();
19483
+ return this.moveCursorToPosition(selectionStart);
19484
+ }
19485
+ this.selection.clearSelection();
19486
+ this.selection.moveCursorBy(-times || -1, 0);
19487
+ };
19488
+ this.navigateDown = function(times) {
19489
+ if (this.selection.isMultiLine() && this.selection.isBackwards()) {
19490
+ var selectionEnd = this.selection.anchor.getPosition();
19491
+ return this.moveCursorToPosition(selectionEnd);
19492
+ }
19493
+ this.selection.clearSelection();
19494
+ this.selection.moveCursorBy(times || 1, 0);
19495
+ };
19496
+ this.navigateLeft = function(times) {
19497
+ if (!this.selection.isEmpty()) {
19498
+ var selectionStart = this.getSelectionRange().start;
19499
+ this.moveCursorToPosition(selectionStart);
19500
+ }
19501
+ else {
19502
+ times = times || 1;
19503
+ while (times--) {
19504
+ this.selection.moveCursorLeft();
19505
+ }
19506
+ }
19507
+ this.clearSelection();
19508
+ };
19509
+ this.navigateRight = function(times) {
19510
+ if (!this.selection.isEmpty()) {
19511
+ var selectionEnd = this.getSelectionRange().end;
19512
+ this.moveCursorToPosition(selectionEnd);
19513
+ }
19514
+ else {
19515
+ times = times || 1;
19516
+ while (times--) {
19517
+ this.selection.moveCursorRight();
19518
+ }
19519
+ }
19520
+ this.clearSelection();
19521
+ };
19522
+ this.navigateLineStart = function() {
19523
+ this.selection.moveCursorLineStart();
19524
+ this.clearSelection();
19525
+ };
19526
+ this.navigateLineEnd = function() {
19527
+ this.selection.moveCursorLineEnd();
19528
+ this.clearSelection();
19529
+ };
19530
+ this.navigateFileEnd = function() {
19531
+ this.selection.moveCursorFileEnd();
19532
+ this.clearSelection();
19533
+ };
19534
+ this.navigateFileStart = function() {
19535
+ this.selection.moveCursorFileStart();
19536
+ this.clearSelection();
19537
+ };
19538
+ this.navigateWordRight = function() {
19539
+ this.selection.moveCursorWordRight();
19540
+ this.clearSelection();
19541
+ };
19542
+ this.navigateWordLeft = function() {
19543
+ this.selection.moveCursorWordLeft();
19544
+ this.clearSelection();
19545
+ };
19546
+ this.replace = function(replacement, options) {
19547
+ if (options)
19548
+ this.$search.set(options);
19549
+
19550
+ var range = this.$search.find(this.session);
19551
+ var replaced = 0;
19552
+ if (!range)
19553
+ return replaced;
19554
+
19555
+ if (this.$tryReplace(range, replacement)) {
19556
+ replaced = 1;
19557
+ }
19558
+ if (range !== null) {
19559
+ this.selection.setSelectionRange(range);
19560
+ this.renderer.scrollSelectionIntoView(range.start, range.end);
19561
+ }
19562
+
19563
+ return replaced;
19564
+ };
19565
+ this.replaceAll = function(replacement, options) {
19566
+ if (options) {
19567
+ this.$search.set(options);
19568
+ }
19569
+
19570
+ var ranges = this.$search.findAll(this.session);
19571
+ var replaced = 0;
19572
+ if (!ranges.length)
19573
+ return replaced;
19574
+
19575
+ this.$blockScrolling += 1;
19576
+
19577
+ var selection = this.getSelectionRange();
19578
+ this.selection.moveTo(0, 0);
19579
+
19580
+ for (var i = ranges.length - 1; i >= 0; --i) {
19581
+ if(this.$tryReplace(ranges[i], replacement)) {
19582
+ replaced++;
19583
+ }
19584
+ }
19585
+
19586
+ this.selection.setSelectionRange(selection);
19587
+ this.$blockScrolling -= 1;
19588
+
19589
+ return replaced;
19590
+ };
19591
+
19592
+ this.$tryReplace = function(range, replacement) {
19593
+ var input = this.session.getTextRange(range);
19594
+ replacement = this.$search.replace(input, replacement);
19595
+ if (replacement !== null) {
19596
+ range.end = this.session.replace(range, replacement);
19597
+ return range;
19598
+ } else {
19599
+ return null;
19600
+ }
19601
+ };
19602
+ this.getLastSearchOptions = function() {
19603
+ return this.$search.getOptions();
19604
+ };
19605
+ this.find = function(needle, options, animate) {
19606
+ if (!options)
19607
+ options = {};
19608
+
19609
+ if (typeof needle == "string" || needle instanceof RegExp)
19610
+ options.needle = needle;
19611
+ else if (typeof needle == "object")
19612
+ oop.mixin(options, needle);
19613
+
19614
+ var range = this.selection.getRange();
19615
+ if (options.needle == null) {
19616
+ needle = this.session.getTextRange(range)
19617
+ || this.$search.$options.needle;
19618
+ if (!needle) {
19619
+ range = this.session.getWordRange(range.start.row, range.start.column);
19620
+ needle = this.session.getTextRange(range);
19621
+ }
19622
+ this.$search.set({needle: needle});
19623
+ }
19624
+
19625
+ this.$search.set(options);
19626
+ if (!options.start)
19627
+ this.$search.set({start: range});
19628
+
19629
+ var newRange = this.$search.find(this.session);
19630
+ if (options.preventScroll)
19631
+ return newRange;
19632
+ if (newRange) {
19633
+ this.revealRange(newRange, animate);
19634
+ return newRange;
19635
+ }
19636
+ if (options.backwards)
19637
+ range.start = range.end;
19638
+ else
19639
+ range.end = range.start;
19640
+ this.selection.setRange(range);
19641
+ };
19642
+ this.findNext = function(options, animate) {
19643
+ this.find({skipCurrent: true, backwards: false}, options, animate);
19644
+ };
19645
+ this.findPrevious = function(options, animate) {
19646
+ this.find(options, {skipCurrent: true, backwards: true}, animate);
19647
+ };
19648
+
19649
+ this.revealRange = function(range, animate) {
19650
+ this.$blockScrolling += 1;
19651
+ this.session.unfold(range);
19652
+ this.selection.setSelectionRange(range);
19653
+ this.$blockScrolling -= 1;
19654
+
19655
+ var scrollTop = this.renderer.scrollTop;
19656
+ this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
19657
+ if (animate !== false)
19658
+ this.renderer.animateScrolling(scrollTop);
19659
+ };
19660
+ this.undo = function() {
19661
+ this.$blockScrolling++;
19662
+ this.session.getUndoManager().undo();
19663
+ this.$blockScrolling--;
19664
+ this.renderer.scrollCursorIntoView(null, 0.5);
19665
+ };
19666
+ this.redo = function() {
19667
+ this.$blockScrolling++;
19668
+ this.session.getUndoManager().redo();
19669
+ this.$blockScrolling--;
19670
+ this.renderer.scrollCursorIntoView(null, 0.5);
19671
+ };
19672
+ this.destroy = function() {
19673
+ this.renderer.destroy();
19674
+ this._signal("destroy", this);
19675
+ if (this.session) {
19676
+ this.session.destroy();
19677
+ }
19678
+ };
19679
+ this.setAutoScrollEditorIntoView = function(enable) {
19680
+ if (!enable)
19681
+ return;
19682
+ var rect;
19683
+ var self = this;
19684
+ var shouldScroll = false;
19685
+ if (!this.$scrollAnchor)
19686
+ this.$scrollAnchor = document.createElement("div");
19687
+ var scrollAnchor = this.$scrollAnchor;
19688
+ scrollAnchor.style.cssText = "position:absolute";
19689
+ this.container.insertBefore(scrollAnchor, this.container.firstChild);
19690
+ var onChangeSelection = this.on("changeSelection", function() {
19691
+ shouldScroll = true;
19692
+ });
19693
+ var onBeforeRender = this.renderer.on("beforeRender", function() {
19694
+ if (shouldScroll)
19695
+ rect = self.renderer.container.getBoundingClientRect();
19696
+ });
19697
+ var onAfterRender = this.renderer.on("afterRender", function() {
19698
+ if (shouldScroll && rect && (self.isFocused()
19699
+ || self.searchBox && self.searchBox.isFocused())
19700
+ ) {
19701
+ var renderer = self.renderer;
19702
+ var pos = renderer.$cursorLayer.$pixelPos;
19703
+ var config = renderer.layerConfig;
19704
+ var top = pos.top - config.offset;
19705
+ if (pos.top >= 0 && top + rect.top < 0) {
19706
+ shouldScroll = true;
19707
+ } else if (pos.top < config.height &&
19708
+ pos.top + rect.top + config.lineHeight > window.innerHeight) {
19709
+ shouldScroll = false;
19710
+ } else {
19711
+ shouldScroll = null;
19712
+ }
19713
+ if (shouldScroll != null) {
19714
+ scrollAnchor.style.top = top + "px";
19715
+ scrollAnchor.style.left = pos.left + "px";
19716
+ scrollAnchor.style.height = config.lineHeight + "px";
19717
+ scrollAnchor.scrollIntoView(shouldScroll);
19718
+ }
19719
+ shouldScroll = rect = null;
19720
+ }
19721
+ });
19722
+ this.setAutoScrollEditorIntoView = function(enable) {
19723
+ if (enable)
19724
+ return;
19725
+ delete this.setAutoScrollEditorIntoView;
19726
+ this.removeEventListener("changeSelection", onChangeSelection);
19727
+ this.renderer.removeEventListener("afterRender", onAfterRender);
19728
+ this.renderer.removeEventListener("beforeRender", onBeforeRender);
19729
+ };
19730
+ };
19731
+
19732
+
19733
+ this.$resetCursorStyle = function() {
19734
+ var style = this.$cursorStyle || "ace";
19735
+ var cursorLayer = this.renderer.$cursorLayer;
19736
+ if (!cursorLayer)
19737
+ return;
19738
+ cursorLayer.setSmoothBlinking(/smooth/.test(style));
19739
+ cursorLayer.isBlinking = !this.$readOnly && style != "wide";
19740
+ dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style));
19741
+ };
19742
+
19743
+ }).call(Editor.prototype);
19744
+
19745
+
19746
+
19747
+ config.defineOptions(Editor.prototype, "editor", {
19748
+ selectionStyle: {
19749
+ set: function(style) {
19750
+ this.onSelectionChange();
19751
+ this._signal("changeSelectionStyle", {data: style});
19752
+ },
19753
+ initialValue: "line"
19754
+ },
19755
+ highlightActiveLine: {
19756
+ set: function() {this.$updateHighlightActiveLine();},
19757
+ initialValue: true
19758
+ },
19759
+ highlightSelectedWord: {
19760
+ set: function(shouldHighlight) {this.$onSelectionChange();},
19761
+ initialValue: true
19762
+ },
19763
+ readOnly: {
19764
+ set: function(readOnly) {
19765
+ this.$resetCursorStyle();
19766
+ },
19767
+ initialValue: false
19768
+ },
19769
+ cursorStyle: {
19770
+ set: function(val) { this.$resetCursorStyle(); },
19771
+ values: ["ace", "slim", "smooth", "wide"],
19772
+ initialValue: "ace"
19773
+ },
19774
+ mergeUndoDeltas: {
19775
+ values: [false, true, "always"],
19776
+ initialValue: true
19777
+ },
19778
+ behavioursEnabled: {initialValue: true},
19779
+ wrapBehavioursEnabled: {initialValue: true},
19780
+ autoScrollEditorIntoView: {
19781
+ set: function(val) {this.setAutoScrollEditorIntoView(val)}
19782
+ },
19783
+
19784
+ hScrollBarAlwaysVisible: "renderer",
19785
+ vScrollBarAlwaysVisible: "renderer",
19786
+ highlightGutterLine: "renderer",
19787
+ animatedScroll: "renderer",
19788
+ showInvisibles: "renderer",
19789
+ showPrintMargin: "renderer",
19790
+ printMarginColumn: "renderer",
19791
+ printMargin: "renderer",
19792
+ fadeFoldWidgets: "renderer",
19793
+ showFoldWidgets: "renderer",
19794
+ showLineNumbers: "renderer",
19795
+ showGutter: "renderer",
19796
+ displayIndentGuides: "renderer",
19797
+ fontSize: "renderer",
19798
+ fontFamily: "renderer",
19799
+ maxLines: "renderer",
19800
+ minLines: "renderer",
19801
+ scrollPastEnd: "renderer",
19802
+ fixedWidthGutter: "renderer",
19803
+ theme: "renderer",
19804
+
19805
+ scrollSpeed: "$mouseHandler",
19806
+ dragDelay: "$mouseHandler",
19807
+ dragEnabled: "$mouseHandler",
19808
+ focusTimout: "$mouseHandler",
19809
+ tooltipFollowsMouse: "$mouseHandler",
19810
+
19811
+ firstLineNumber: "session",
19812
+ overwrite: "session",
19813
+ newLineMode: "session",
19814
+ useWorker: "session",
19815
+ useSoftTabs: "session",
19816
+ tabSize: "session",
19817
+ wrap: "session",
19818
+ foldStyle: "session",
19819
+ mode: "session"
19820
+ });
19821
+
19822
+ exports.Editor = Editor;
19823
+ });
19824
+
19825
+ ace.define("ace/undomanager",["require","exports","module"], function(acequire, exports, module) {
19826
+ "use strict";
19827
+ var UndoManager = function() {
19828
+ this.reset();
19829
+ };
19830
+
19831
+ (function() {
19832
+ this.execute = function(options) {
19833
+ var deltas = options.args[0];
19834
+ this.$doc = options.args[1];
19835
+ if (options.merge && this.hasUndo()){
19836
+ this.dirtyCounter--;
19837
+ deltas = this.$undoStack.pop().concat(deltas);
19838
+ }
19839
+ this.$undoStack.push(deltas);
19840
+ this.$redoStack = [];
19841
+
19842
+ if (this.dirtyCounter < 0) {
19843
+ this.dirtyCounter = NaN;
19844
+ }
19845
+ this.dirtyCounter++;
19846
+ };
19847
+ this.undo = function(dontSelect) {
19848
+ var deltas = this.$undoStack.pop();
19849
+ var undoSelectionRange = null;
19850
+ if (deltas) {
19851
+ undoSelectionRange =
19852
+ this.$doc.undoChanges(deltas, dontSelect);
19853
+ this.$redoStack.push(deltas);
19854
+ this.dirtyCounter--;
19855
+ }
19856
+
19857
+ return undoSelectionRange;
19858
+ };
19859
+ this.redo = function(dontSelect) {
19860
+ var deltas = this.$redoStack.pop();
19861
+ var redoSelectionRange = null;
19862
+ if (deltas) {
19863
+ redoSelectionRange =
19864
+ this.$doc.redoChanges(deltas, dontSelect);
19865
+ this.$undoStack.push(deltas);
19866
+ this.dirtyCounter++;
19867
+ }
19868
+
19869
+ return redoSelectionRange;
19870
+ };
19871
+ this.reset = function() {
19872
+ this.$undoStack = [];
19873
+ this.$redoStack = [];
19874
+ this.dirtyCounter = 0;
19875
+ };
19876
+ this.hasUndo = function() {
19877
+ return this.$undoStack.length > 0;
19878
+ };
19879
+ this.hasRedo = function() {
19880
+ return this.$redoStack.length > 0;
19881
+ };
19882
+ this.markClean = function() {
19883
+ this.dirtyCounter = 0;
19884
+ };
19885
+ this.isClean = function() {
19886
+ return this.dirtyCounter === 0;
19887
+ };
19888
+
19889
+ }).call(UndoManager.prototype);
19890
+
19891
+ exports.UndoManager = UndoManager;
19892
+ });
19893
+
19894
+ ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(acequire, exports, module) {
19895
+ "use strict";
19896
+
19897
+ var dom = acequire("../lib/dom");
19898
+ var oop = acequire("../lib/oop");
19899
+ var lang = acequire("../lib/lang");
19900
+ var EventEmitter = acequire("../lib/event_emitter").EventEmitter;
19901
+
19902
+ var Gutter = function(parentEl) {
19903
+ this.element = dom.createElement("div");
19904
+ this.element.className = "ace_layer ace_gutter-layer";
19905
+ parentEl.appendChild(this.element);
19906
+ this.setShowFoldWidgets(this.$showFoldWidgets);
19907
+
19908
+ this.gutterWidth = 0;
19909
+
19910
+ this.$annotations = [];
19911
+ this.$updateAnnotations = this.$updateAnnotations.bind(this);
19912
+
19913
+ this.$cells = [];
19914
+ };
19915
+
19916
+ (function() {
19917
+
19918
+ oop.implement(this, EventEmitter);
19919
+
19920
+ this.setSession = function(session) {
19921
+ if (this.session)
19922
+ this.session.removeEventListener("change", this.$updateAnnotations);
19923
+ this.session = session;
19924
+ if (session)
19925
+ session.on("change", this.$updateAnnotations);
19926
+ };
19927
+
19928
+ this.addGutterDecoration = function(row, className){
19929
+ if (window.console)
19930
+ console.warn && console.warn("deprecated use session.addGutterDecoration");
19931
+ this.session.addGutterDecoration(row, className);
19932
+ };
19933
+
19934
+ this.removeGutterDecoration = function(row, className){
19935
+ if (window.console)
19936
+ console.warn && console.warn("deprecated use session.removeGutterDecoration");
19937
+ this.session.removeGutterDecoration(row, className);
19938
+ };
19939
+
19940
+ this.setAnnotations = function(annotations) {
19941
+ this.$annotations = [];
19942
+ for (var i = 0; i < annotations.length; i++) {
19943
+ var annotation = annotations[i];
19944
+ var row = annotation.row;
19945
+ var rowInfo = this.$annotations[row];
19946
+ if (!rowInfo)
19947
+ rowInfo = this.$annotations[row] = {text: []};
19948
+
19949
+ var annoText = annotation.text;
19950
+ annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || "";
19951
+
19952
+ if (rowInfo.text.indexOf(annoText) === -1)
19953
+ rowInfo.text.push(annoText);
19954
+
19955
+ var type = annotation.type;
19956
+ if (type == "error")
19957
+ rowInfo.className = " ace_error";
19958
+ else if (type == "warning" && rowInfo.className != " ace_error")
19959
+ rowInfo.className = " ace_warning";
19960
+ else if (type == "info" && (!rowInfo.className))
19961
+ rowInfo.className = " ace_info";
19962
+ }
19963
+ };
19964
+
19965
+ this.$updateAnnotations = function (e) {
19966
+ if (!this.$annotations.length)
19967
+ return;
19968
+ var delta = e.data;
19969
+ var range = delta.range;
19970
+ var firstRow = range.start.row;
19971
+ var len = range.end.row - firstRow;
19972
+ if (len === 0) {
19973
+ } else if (delta.action == "removeText" || delta.action == "removeLines") {
19974
+ this.$annotations.splice(firstRow, len + 1, null);
19975
+ } else {
19976
+ var args = new Array(len + 1);
19977
+ args.unshift(firstRow, 1);
19978
+ this.$annotations.splice.apply(this.$annotations, args);
19979
+ }
19980
+ };
19981
+
19982
+ this.update = function(config) {
19983
+ var session = this.session;
19984
+ var firstRow = config.firstRow;
19985
+ var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
19986
+ session.getLength() - 1);
19987
+ var fold = session.getNextFoldLine(firstRow);
19988
+ var foldStart = fold ? fold.start.row : Infinity;
19989
+ var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
19990
+ var breakpoints = session.$breakpoints;
19991
+ var decorations = session.$decorations;
19992
+ var firstLineNumber = session.$firstLineNumber;
19993
+ var lastLineNumber = 0;
19994
+
19995
+ var gutterRenderer = session.gutterRenderer || this.$renderer;
19996
+
19997
+ var cell = null;
19998
+ var index = -1;
19999
+ var row = firstRow;
20000
+ while (true) {
20001
+ if (row > foldStart) {
20002
+ row = fold.end.row + 1;
20003
+ fold = session.getNextFoldLine(row, fold);
20004
+ foldStart = fold ? fold.start.row : Infinity;
20005
+ }
20006
+ if (row > lastRow) {
20007
+ while (this.$cells.length > index + 1) {
20008
+ cell = this.$cells.pop();
20009
+ this.element.removeChild(cell.element);
20010
+ }
20011
+ break;
20012
+ }
20013
+
20014
+ cell = this.$cells[++index];
20015
+ if (!cell) {
20016
+ cell = {element: null, textNode: null, foldWidget: null};
20017
+ cell.element = dom.createElement("div");
20018
+ cell.textNode = document.createTextNode('');
20019
+ cell.element.appendChild(cell.textNode);
20020
+ this.element.appendChild(cell.element);
20021
+ this.$cells[index] = cell;
20022
+ }
20023
+
20024
+ var className = "ace_gutter-cell ";
20025
+ if (breakpoints[row])
20026
+ className += breakpoints[row];
20027
+ if (decorations[row])
20028
+ className += decorations[row];
20029
+ if (this.$annotations[row])
20030
+ className += this.$annotations[row].className;
20031
+ if (cell.element.className != className)
20032
+ cell.element.className = className;
20033
+
20034
+ var height = session.getRowLength(row) * config.lineHeight + "px";
20035
+ if (height != cell.element.style.height)
20036
+ cell.element.style.height = height;
20037
+
20038
+ if (foldWidgets) {
20039
+ var c = foldWidgets[row];
20040
+ if (c == null)
20041
+ c = foldWidgets[row] = session.getFoldWidget(row);
20042
+ }
20043
+
20044
+ if (c) {
20045
+ if (!cell.foldWidget) {
20046
+ cell.foldWidget = dom.createElement("span");
20047
+ cell.element.appendChild(cell.foldWidget);
20048
+ }
20049
+ var className = "ace_fold-widget ace_" + c;
20050
+ if (c == "start" && row == foldStart && row < fold.end.row)
20051
+ className += " ace_closed";
20052
+ else
20053
+ className += " ace_open";
20054
+ if (cell.foldWidget.className != className)
20055
+ cell.foldWidget.className = className;
20056
+
20057
+ var height = config.lineHeight + "px";
20058
+ if (cell.foldWidget.style.height != height)
20059
+ cell.foldWidget.style.height = height;
20060
+ } else {
20061
+ if (cell.foldWidget) {
20062
+ cell.element.removeChild(cell.foldWidget);
20063
+ cell.foldWidget = null;
20064
+ }
20065
+ }
20066
+
20067
+ var text = lastLineNumber = gutterRenderer
20068
+ ? gutterRenderer.getText(session, row)
20069
+ : row + firstLineNumber;
20070
+ if (text != cell.textNode.data)
20071
+ cell.textNode.data = text;
20072
+
20073
+ row++;
20074
+ }
20075
+
20076
+ this.element.style.height = config.minHeight + "px";
20077
+
20078
+ if (this.$fixedWidth || session.$useWrapMode)
20079
+ lastLineNumber = session.getLength() + firstLineNumber;
20080
+
20081
+ var gutterWidth = gutterRenderer
20082
+ ? gutterRenderer.getWidth(session, lastLineNumber, config)
20083
+ : lastLineNumber.toString().length * config.characterWidth;
20084
+
20085
+ var padding = this.$padding || this.$computePadding();
20086
+ gutterWidth += padding.left + padding.right;
20087
+ if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
20088
+ this.gutterWidth = gutterWidth;
20089
+ this.element.style.width = Math.ceil(this.gutterWidth) + "px";
20090
+ this._emit("changeGutterWidth", gutterWidth);
20091
+ }
20092
+ };
20093
+
20094
+ this.$fixedWidth = false;
20095
+
20096
+ this.$showLineNumbers = true;
20097
+ this.$renderer = "";
20098
+ this.setShowLineNumbers = function(show) {
20099
+ this.$renderer = !show && {
20100
+ getWidth: function() {return ""},
20101
+ getText: function() {return ""}
20102
+ };
20103
+ };
20104
+
20105
+ this.getShowLineNumbers = function() {
20106
+ return this.$showLineNumbers;
20107
+ };
20108
+
20109
+ this.$showFoldWidgets = true;
20110
+ this.setShowFoldWidgets = function(show) {
20111
+ if (show)
20112
+ dom.addCssClass(this.element, "ace_folding-enabled");
20113
+ else
20114
+ dom.removeCssClass(this.element, "ace_folding-enabled");
20115
+
20116
+ this.$showFoldWidgets = show;
20117
+ this.$padding = null;
20118
+ };
20119
+
20120
+ this.getShowFoldWidgets = function() {
20121
+ return this.$showFoldWidgets;
20122
+ };
20123
+
20124
+ this.$computePadding = function() {
20125
+ if (!this.element.firstChild)
20126
+ return {left: 0, right: 0};
20127
+ var style = dom.computedStyle(this.element.firstChild);
20128
+ this.$padding = {};
20129
+ this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;
20130
+ this.$padding.right = parseInt(style.paddingRight) || 0;
20131
+ return this.$padding;
20132
+ };
20133
+
20134
+ this.getRegion = function(point) {
20135
+ var padding = this.$padding || this.$computePadding();
20136
+ var rect = this.element.getBoundingClientRect();
20137
+ if (point.x < padding.left + rect.left)
20138
+ return "markers";
20139
+ if (this.$showFoldWidgets && point.x > rect.right - padding.right)
20140
+ return "foldWidgets";
20141
+ };
20142
+
20143
+ }).call(Gutter.prototype);
20144
+
20145
+ exports.Gutter = Gutter;
20146
+
20147
+ });
20148
+
20149
+ ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(acequire, exports, module) {
20150
+ "use strict";
20151
+
20152
+ var Range = acequire("../range").Range;
20153
+ var dom = acequire("../lib/dom");
20154
+
20155
+ var Marker = function(parentEl) {
20156
+ this.element = dom.createElement("div");
20157
+ this.element.className = "ace_layer ace_marker-layer";
20158
+ parentEl.appendChild(this.element);
20159
+ };
20160
+
20161
+ (function() {
20162
+
20163
+ this.$padding = 0;
20164
+
20165
+ this.setPadding = function(padding) {
20166
+ this.$padding = padding;
20167
+ };
20168
+ this.setSession = function(session) {
20169
+ this.session = session;
20170
+ };
20171
+
20172
+ this.setMarkers = function(markers) {
20173
+ this.markers = markers;
20174
+ };
20175
+
20176
+ this.update = function(config) {
20177
+ var config = config || this.config;
20178
+ if (!config)
20179
+ return;
20180
+
20181
+ this.config = config;
20182
+
20183
+
20184
+ var html = [];
20185
+ for (var key in this.markers) {
20186
+ var marker = this.markers[key];
20187
+
20188
+ if (!marker.range) {
20189
+ marker.update(html, this, this.session, config);
20190
+ continue;
20191
+ }
20192
+
20193
+ var range = marker.range.clipRows(config.firstRow, config.lastRow);
20194
+ if (range.isEmpty()) continue;
20195
+
20196
+ range = range.toScreenRange(this.session);
20197
+ if (marker.renderer) {
20198
+ var top = this.$getTop(range.start.row, config);
20199
+ var left = this.$padding + range.start.column * config.characterWidth;
20200
+ marker.renderer(html, range, left, top, config);
20201
+ } else if (marker.type == "fullLine") {
20202
+ this.drawFullLineMarker(html, range, marker.clazz, config);
20203
+ } else if (marker.type == "screenLine") {
20204
+ this.drawScreenLineMarker(html, range, marker.clazz, config);
20205
+ } else if (range.isMultiLine()) {
20206
+ if (marker.type == "text")
20207
+ this.drawTextMarker(html, range, marker.clazz, config);
20208
+ else
20209
+ this.drawMultiLineMarker(html, range, marker.clazz, config);
20210
+ } else {
20211
+ this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
20212
+ }
20213
+ }
20214
+ this.element.innerHTML = html.join("");
20215
+ };
20216
+
20217
+ this.$getTop = function(row, layerConfig) {
20218
+ return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
20219
+ };
20220
+ this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
20221
+ var row = range.start.row;
20222
+
20223
+ var lineRange = new Range(
20224
+ row, range.start.column,
20225
+ row, this.session.getScreenLastRowColumn(row)
20226
+ );
20227
+ this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
20228
+ row = range.end.row;
20229
+ lineRange = new Range(row, 0, row, range.end.column);
20230
+ this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
20231
+
20232
+ for (row = range.start.row + 1; row < range.end.row; row++) {
20233
+ lineRange.start.row = row;
20234
+ lineRange.end.row = row;
20235
+ lineRange.end.column = this.session.getScreenLastRowColumn(row);
20236
+ this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
20237
+ }
20238
+ };
20239
+ this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
20240
+ var padding = this.$padding;
20241
+ var height = config.lineHeight;
20242
+ var top = this.$getTop(range.start.row, config);
20243
+ var left = padding + range.start.column * config.characterWidth;
20244
+ extraStyle = extraStyle || "";
20245
+
20246
+ stringBuilder.push(
20247
+ "<div class='", clazz, " ace_start' style='",
20248
+ "height:", height, "px;",
20249
+ "right:0;",
20250
+ "top:", top, "px;",
20251
+ "left:", left, "px;", extraStyle, "'></div>"
20252
+ );
20253
+ top = this.$getTop(range.end.row, config);
20254
+ var width = range.end.column * config.characterWidth;
20255
+
20256
+ stringBuilder.push(
20257
+ "<div class='", clazz, "' style='",
20258
+ "height:", height, "px;",
20259
+ "width:", width, "px;",
20260
+ "top:", top, "px;",
20261
+ "left:", padding, "px;", extraStyle, "'></div>"
20262
+ );
20263
+ height = (range.end.row - range.start.row - 1) * config.lineHeight;
20264
+ if (height < 0)
20265
+ return;
20266
+ top = this.$getTop(range.start.row + 1, config);
20267
+
20268
+ stringBuilder.push(
20269
+ "<div class='", clazz, "' style='",
20270
+ "height:", height, "px;",
20271
+ "right:0;",
20272
+ "top:", top, "px;",
20273
+ "left:", padding, "px;", extraStyle, "'></div>"
20274
+ );
20275
+ };
20276
+ this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {
20277
+ var height = config.lineHeight;
20278
+ var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;
20279
+
20280
+ var top = this.$getTop(range.start.row, config);
20281
+ var left = this.$padding + range.start.column * config.characterWidth;
20282
+
20283
+ stringBuilder.push(
20284
+ "<div class='", clazz, "' style='",
20285
+ "height:", height, "px;",
20286
+ "width:", width, "px;",
20287
+ "top:", top, "px;",
20288
+ "left:", left, "px;", extraStyle || "", "'></div>"
20289
+ );
20290
+ };
20291
+
20292
+ this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
20293
+ var top = this.$getTop(range.start.row, config);
20294
+ var height = config.lineHeight;
20295
+ if (range.start.row != range.end.row)
20296
+ height += this.$getTop(range.end.row, config) - top;
20297
+
20298
+ stringBuilder.push(
20299
+ "<div class='", clazz, "' style='",
20300
+ "height:", height, "px;",
20301
+ "top:", top, "px;",
20302
+ "left:0;right:0;", extraStyle || "", "'></div>"
20303
+ );
20304
+ };
20305
+
20306
+ this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
20307
+ var top = this.$getTop(range.start.row, config);
20308
+ var height = config.lineHeight;
20309
+
20310
+ stringBuilder.push(
20311
+ "<div class='", clazz, "' style='",
20312
+ "height:", height, "px;",
20313
+ "top:", top, "px;",
20314
+ "left:0;right:0;", extraStyle || "", "'></div>"
20315
+ );
20316
+ };
20317
+
20318
+ }).call(Marker.prototype);
20319
+
20320
+ exports.Marker = Marker;
20321
+
20322
+ });
20323
+
20324
+ ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) {
20325
+ "use strict";
20326
+
20327
+ var oop = acequire("../lib/oop");
20328
+ var dom = acequire("../lib/dom");
20329
+ var lang = acequire("../lib/lang");
20330
+ var useragent = acequire("../lib/useragent");
20331
+ var EventEmitter = acequire("../lib/event_emitter").EventEmitter;
20332
+
20333
+ var Text = function(parentEl) {
20334
+ this.element = dom.createElement("div");
20335
+ this.element.className = "ace_layer ace_text-layer";
20336
+ parentEl.appendChild(this.element);
20337
+ this.$updateEolChar = this.$updateEolChar.bind(this);
20338
+ };
20339
+
20340
+ (function() {
20341
+
20342
+ oop.implement(this, EventEmitter);
20343
+
20344
+ this.EOF_CHAR = "\xB6";
20345
+ this.EOL_CHAR_LF = "\xAC";
20346
+ this.EOL_CHAR_CRLF = "\xa4";
20347
+ this.EOL_CHAR = this.EOL_CHAR_LF;
20348
+ this.TAB_CHAR = "\u2192"; //"\u21E5";
20349
+ this.SPACE_CHAR = "\xB7";
20350
+ this.$padding = 0;
20351
+
20352
+ this.$updateEolChar = function() {
20353
+ var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n"
20354
+ ? this.EOL_CHAR_LF
20355
+ : this.EOL_CHAR_CRLF;
20356
+ if (this.EOL_CHAR != EOL_CHAR) {
20357
+ this.EOL_CHAR = EOL_CHAR;
20358
+ return true;
20359
+ }
20360
+ }
20361
+
20362
+ this.setPadding = function(padding) {
20363
+ this.$padding = padding;
20364
+ this.element.style.padding = "0 " + padding + "px";
20365
+ };
20366
+
20367
+ this.getLineHeight = function() {
20368
+ return this.$fontMetrics.$characterSize.height || 0;
20369
+ };
20370
+
20371
+ this.getCharacterWidth = function() {
20372
+ return this.$fontMetrics.$characterSize.width || 0;
20373
+ };
20374
+
20375
+ this.$setFontMetrics = function(measure) {
20376
+ this.$fontMetrics = measure;
20377
+ this.$fontMetrics.on("changeCharacterSize", function(e) {
20378
+ this._signal("changeCharacterSize", e);
20379
+ }.bind(this));
20380
+ this.$pollSizeChanges();
20381
+ }
20382
+
20383
+ this.checkForSizeChanges = function() {
20384
+ this.$fontMetrics.checkForSizeChanges();
20385
+ };
20386
+ this.$pollSizeChanges = function() {
20387
+ return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges();
20388
+ };
20389
+ this.setSession = function(session) {
20390
+ this.session = session;
20391
+ if (session)
20392
+ this.$computeTabString();
20393
+ };
20394
+
20395
+ this.showInvisibles = false;
20396
+ this.setShowInvisibles = function(showInvisibles) {
20397
+ if (this.showInvisibles == showInvisibles)
20398
+ return false;
20399
+
20400
+ this.showInvisibles = showInvisibles;
20401
+ this.$computeTabString();
20402
+ return true;
20403
+ };
20404
+
20405
+ this.displayIndentGuides = true;
20406
+ this.setDisplayIndentGuides = function(display) {
20407
+ if (this.displayIndentGuides == display)
20408
+ return false;
20409
+
20410
+ this.displayIndentGuides = display;
20411
+ this.$computeTabString();
20412
+ return true;
20413
+ };
20414
+
20415
+ this.$tabStrings = [];
20416
+ this.onChangeTabSize =
20417
+ this.$computeTabString = function() {
20418
+ var tabSize = this.session.getTabSize();
20419
+ this.tabSize = tabSize;
20420
+ var tabStr = this.$tabStrings = [0];
20421
+ for (var i = 1; i < tabSize + 1; i++) {
20422
+ if (this.showInvisibles) {
20423
+ tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
20424
+ + this.TAB_CHAR
20425
+ + lang.stringRepeat("\xa0", i - 1)
20426
+ + "</span>");
20427
+ } else {
20428
+ tabStr.push(lang.stringRepeat("\xa0", i));
20429
+ }
20430
+ }
20431
+ if (this.displayIndentGuides) {
20432
+ this.$indentGuideRe = /\s\S| \t|\t |\s$/;
20433
+ var className = "ace_indent-guide";
20434
+ var spaceClass = "";
20435
+ var tabClass = "";
20436
+ if (this.showInvisibles) {
20437
+ className += " ace_invisible";
20438
+ spaceClass = " ace_invisible_space";
20439
+ tabClass = " ace_invisible_tab";
20440
+ var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
20441
+ var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1);
20442
+ } else{
20443
+ var spaceContent = lang.stringRepeat("\xa0", this.tabSize);
20444
+ var tabContent = spaceContent;
20445
+ }
20446
+
20447
+ this.$tabStrings[" "] = "<span class='" + className + spaceClass + "'>" + spaceContent + "</span>";
20448
+ this.$tabStrings["\t"] = "<span class='" + className + tabClass + "'>" + tabContent + "</span>";
20449
+ }
20450
+ };
20451
+
20452
+ this.updateLines = function(config, firstRow, lastRow) {
20453
+ if (this.config.lastRow != config.lastRow ||
20454
+ this.config.firstRow != config.firstRow) {
20455
+ this.scrollLines(config);
20456
+ }
20457
+ this.config = config;
20458
+
20459
+ var first = Math.max(firstRow, config.firstRow);
20460
+ var last = Math.min(lastRow, config.lastRow);
20461
+
20462
+ var lineElements = this.element.childNodes;
20463
+ var lineElementsIdx = 0;
20464
+
20465
+ for (var row = config.firstRow; row < first; row++) {
20466
+ var foldLine = this.session.getFoldLine(row);
20467
+ if (foldLine) {
20468
+ if (foldLine.containsRow(first)) {
20469
+ first = foldLine.start.row;
20470
+ break;
20471
+ } else {
20472
+ row = foldLine.end.row;
20473
+ }
20474
+ }
20475
+ lineElementsIdx ++;
20476
+ }
20477
+
20478
+ var row = first;
20479
+ var foldLine = this.session.getNextFoldLine(row);
20480
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
20481
+
20482
+ while (true) {
20483
+ if (row > foldStart) {
20484
+ row = foldLine.end.row+1;
20485
+ foldLine = this.session.getNextFoldLine(row, foldLine);
20486
+ foldStart = foldLine ? foldLine.start.row :Infinity;
20487
+ }
20488
+ if (row > last)
20489
+ break;
20490
+
20491
+ var lineElement = lineElements[lineElementsIdx++];
20492
+ if (lineElement) {
20493
+ var html = [];
20494
+ this.$renderLine(
20495
+ html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false
20496
+ );
20497
+ lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
20498
+ lineElement.innerHTML = html.join("");
20499
+ }
20500
+ row++;
20501
+ }
20502
+ };
20503
+
20504
+ this.scrollLines = function(config) {
20505
+ var oldConfig = this.config;
20506
+ this.config = config;
20507
+
20508
+ if (!oldConfig || oldConfig.lastRow < config.firstRow)
20509
+ return this.update(config);
20510
+
20511
+ if (config.lastRow < oldConfig.firstRow)
20512
+ return this.update(config);
20513
+
20514
+ var el = this.element;
20515
+ if (oldConfig.firstRow < config.firstRow)
20516
+ for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)
20517
+ el.removeChild(el.firstChild);
20518
+
20519
+ if (oldConfig.lastRow > config.lastRow)
20520
+ for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
20521
+ el.removeChild(el.lastChild);
20522
+
20523
+ if (config.firstRow < oldConfig.firstRow) {
20524
+ var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);
20525
+ if (el.firstChild)
20526
+ el.insertBefore(fragment, el.firstChild);
20527
+ else
20528
+ el.appendChild(fragment);
20529
+ }
20530
+
20531
+ if (config.lastRow > oldConfig.lastRow) {
20532
+ var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
20533
+ el.appendChild(fragment);
20534
+ }
20535
+ };
20536
+
20537
+ this.$renderLinesFragment = function(config, firstRow, lastRow) {
20538
+ var fragment = this.element.ownerDocument.createDocumentFragment();
20539
+ var row = firstRow;
20540
+ var foldLine = this.session.getNextFoldLine(row);
20541
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
20542
+
20543
+ while (true) {
20544
+ if (row > foldStart) {
20545
+ row = foldLine.end.row+1;
20546
+ foldLine = this.session.getNextFoldLine(row, foldLine);
20547
+ foldStart = foldLine ? foldLine.start.row : Infinity;
20548
+ }
20549
+ if (row > lastRow)
20550
+ break;
20551
+
20552
+ var container = dom.createElement("div");
20553
+
20554
+ var html = [];
20555
+ this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
20556
+ container.innerHTML = html.join("");
20557
+ if (this.$useLineGroups()) {
20558
+ container.className = 'ace_line_group';
20559
+ fragment.appendChild(container);
20560
+ container.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
20561
+
20562
+ } else {
20563
+ while(container.firstChild)
20564
+ fragment.appendChild(container.firstChild);
20565
+ }
20566
+
20567
+ row++;
20568
+ }
20569
+ return fragment;
20570
+ };
20571
+
20572
+ this.update = function(config) {
20573
+ this.config = config;
20574
+
20575
+ var html = [];
20576
+ var firstRow = config.firstRow, lastRow = config.lastRow;
20577
+
20578
+ var row = firstRow;
20579
+ var foldLine = this.session.getNextFoldLine(row);
20580
+ var foldStart = foldLine ? foldLine.start.row : Infinity;
20581
+
20582
+ while (true) {
20583
+ if (row > foldStart) {
20584
+ row = foldLine.end.row+1;
20585
+ foldLine = this.session.getNextFoldLine(row, foldLine);
20586
+ foldStart = foldLine ? foldLine.start.row :Infinity;
20587
+ }
20588
+ if (row > lastRow)
20589
+ break;
20590
+
20591
+ if (this.$useLineGroups())
20592
+ html.push("<div class='ace_line_group' style='height:", config.lineHeight*this.session.getRowLength(row), "px'>")
20593
+
20594
+ this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
20595
+
20596
+ if (this.$useLineGroups())
20597
+ html.push("</div>"); // end the line group
20598
+
20599
+ row++;
20600
+ }
20601
+ this.element.innerHTML = html.join("");
20602
+ };
20603
+
20604
+ this.$textToken = {
20605
+ "text": true,
20606
+ "rparen": true,
20607
+ "lparen": true
20608
+ };
20609
+
20610
+ this.$renderToken = function(stringBuilder, screenColumn, token, value) {
20611
+ var self = this;
20612
+ var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
20613
+ var replaceFunc = function(c, a, b, tabIdx, idx4) {
20614
+ if (a) {
20615
+ return self.showInvisibles ?
20616
+ "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" :
20617
+ lang.stringRepeat("\xa0", c.length);
20618
+ } else if (c == "&") {
20619
+ return "&#38;";
20620
+ } else if (c == "<") {
20621
+ return "&#60;";
20622
+ } else if (c == "\t") {
20623
+ var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
20624
+ screenColumn += tabSize - 1;
20625
+ return self.$tabStrings[tabSize];
20626
+ } else if (c == "\u3000") {
20627
+ var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk";
20628
+ var space = self.showInvisibles ? self.SPACE_CHAR : "";
20629
+ screenColumn += 1;
20630
+ return "<span class='" + classToUse + "' style='width:" +
20631
+ (self.config.characterWidth * 2) +
20632
+ "px'>" + space + "</span>";
20633
+ } else if (b) {
20634
+ return "<span class='ace_invisible ace_invisible_space ace_invalid'>" + self.SPACE_CHAR + "</span>";
20635
+ } else {
20636
+ screenColumn += 1;
20637
+ return "<span class='ace_cjk' style='width:" +
20638
+ (self.config.characterWidth * 2) +
20639
+ "px'>" + c + "</span>";
20640
+ }
20641
+ };
20642
+
20643
+ var output = value.replace(replaceReg, replaceFunc);
20644
+
20645
+ if (!this.$textToken[token.type]) {
20646
+ var classes = "ace_" + token.type.replace(/\./g, " ace_");
20647
+ var style = "";
20648
+ if (token.type == "fold")
20649
+ style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' ";
20650
+ stringBuilder.push("<span class='", classes, "'", style, ">", output, "</span>");
20651
+ }
20652
+ else {
20653
+ stringBuilder.push(output);
20654
+ }
20655
+ return screenColumn + value.length;
20656
+ };
20657
+
20658
+ this.renderIndentGuide = function(stringBuilder, value, max) {
20659
+ var cols = value.search(this.$indentGuideRe);
20660
+ if (cols <= 0 || cols >= max)
20661
+ return value;
20662
+ if (value[0] == " ") {
20663
+ cols -= cols % this.tabSize;
20664
+ stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize));
20665
+ return value.substr(cols);
20666
+ } else if (value[0] == "\t") {
20667
+ stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols));
20668
+ return value.substr(cols);
20669
+ }
20670
+ return value;
20671
+ };
20672
+
20673
+ this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) {
20674
+ var chars = 0;
20675
+ var split = 0;
20676
+ var splitChars = splits[0];
20677
+ var screenColumn = 0;
20678
+
20679
+ for (var i = 0; i < tokens.length; i++) {
20680
+ var token = tokens[i];
20681
+ var value = token.value;
20682
+ if (i == 0 && this.displayIndentGuides) {
20683
+ chars = value.length;
20684
+ value = this.renderIndentGuide(stringBuilder, value, splitChars);
20685
+ if (!value)
20686
+ continue;
20687
+ chars -= value.length;
20688
+ }
20689
+
20690
+ if (chars + value.length < splitChars) {
20691
+ screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
20692
+ chars += value.length;
20693
+ } else {
20694
+ while (chars + value.length >= splitChars) {
20695
+ screenColumn = this.$renderToken(
20696
+ stringBuilder, screenColumn,
20697
+ token, value.substring(0, splitChars - chars)
20698
+ );
20699
+ value = value.substring(splitChars - chars);
20700
+ chars = splitChars;
20701
+
20702
+ if (!onlyContents) {
20703
+ stringBuilder.push("</div>",
20704
+ "<div class='ace_line' style='height:",
20705
+ this.config.lineHeight, "px'>"
20706
+ );
20707
+ }
20708
+
20709
+ split ++;
20710
+ screenColumn = 0;
20711
+ splitChars = splits[split] || Number.MAX_VALUE;
20712
+ }
20713
+ if (value.length != 0) {
20714
+ chars += value.length;
20715
+ screenColumn = this.$renderToken(
20716
+ stringBuilder, screenColumn, token, value
20717
+ );
20718
+ }
20719
+ }
20720
+ }
20721
+ };
20722
+
20723
+ this.$renderSimpleLine = function(stringBuilder, tokens) {
20724
+ var screenColumn = 0;
20725
+ var token = tokens[0];
20726
+ var value = token.value;
20727
+ if (this.displayIndentGuides)
20728
+ value = this.renderIndentGuide(stringBuilder, value);
20729
+ if (value)
20730
+ screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
20731
+ for (var i = 1; i < tokens.length; i++) {
20732
+ token = tokens[i];
20733
+ value = token.value;
20734
+ screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
20735
+ }
20736
+ };
20737
+ this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) {
20738
+ if (!foldLine && foldLine != false)
20739
+ foldLine = this.session.getFoldLine(row);
20740
+
20741
+ if (foldLine)
20742
+ var tokens = this.$getFoldLineTokens(row, foldLine);
20743
+ else
20744
+ var tokens = this.session.getTokens(row);
20745
+
20746
+
20747
+ if (!onlyContents) {
20748
+ stringBuilder.push(
20749
+ "<div class='ace_line' style='height:",
20750
+ this.config.lineHeight * (
20751
+ this.$useLineGroups() ? 1 :this.session.getRowLength(row)
20752
+ ), "px'>"
20753
+ );
20754
+ }
20755
+
20756
+ if (tokens.length) {
20757
+ var splits = this.session.getRowSplitData(row);
20758
+ if (splits && splits.length)
20759
+ this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents);
20760
+ else
20761
+ this.$renderSimpleLine(stringBuilder, tokens);
20762
+ }
20763
+
20764
+ if (this.showInvisibles) {
20765
+ if (foldLine)
20766
+ row = foldLine.end.row
20767
+
20768
+ stringBuilder.push(
20769
+ "<span class='ace_invisible ace_invisible_eol'>",
20770
+ row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR,
20771
+ "</span>"
20772
+ );
20773
+ }
20774
+ if (!onlyContents)
20775
+ stringBuilder.push("</div>");
20776
+ };
20777
+
20778
+ this.$getFoldLineTokens = function(row, foldLine) {
20779
+ var session = this.session;
20780
+ var renderTokens = [];
20781
+
20782
+ function addTokens(tokens, from, to) {
20783
+ var idx = 0, col = 0;
20784
+ while ((col + tokens[idx].value.length) < from) {
20785
+ col += tokens[idx].value.length;
20786
+ idx++;
20787
+
20788
+ if (idx == tokens.length)
20789
+ return;
20790
+ }
20791
+ if (col != from) {
20792
+ var value = tokens[idx].value.substring(from - col);
20793
+ if (value.length > (to - from))
20794
+ value = value.substring(0, to - from);
20795
+
20796
+ renderTokens.push({
20797
+ type: tokens[idx].type,
20798
+ value: value
20799
+ });
20800
+
20801
+ col = from + value.length;
20802
+ idx += 1;
20803
+ }
20804
+
20805
+ while (col < to && idx < tokens.length) {
20806
+ var value = tokens[idx].value;
20807
+ if (value.length + col > to) {
20808
+ renderTokens.push({
20809
+ type: tokens[idx].type,
20810
+ value: value.substring(0, to - col)
20811
+ });
20812
+ } else
20813
+ renderTokens.push(tokens[idx]);
20814
+ col += value.length;
20815
+ idx += 1;
20816
+ }
20817
+ }
20818
+
20819
+ var tokens = session.getTokens(row);
20820
+ foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
20821
+ if (placeholder != null) {
20822
+ renderTokens.push({
20823
+ type: "fold",
20824
+ value: placeholder
20825
+ });
20826
+ } else {
20827
+ if (isNewRow)
20828
+ tokens = session.getTokens(row);
20829
+
20830
+ if (tokens.length)
20831
+ addTokens(tokens, lastColumn, column);
20832
+ }
20833
+ }, foldLine.end.row, this.session.getLine(foldLine.end.row).length);
20834
+
20835
+ return renderTokens;
20836
+ };
20837
+
20838
+ this.$useLineGroups = function() {
20839
+ return this.session.getUseWrapMode();
20840
+ };
20841
+
20842
+ this.destroy = function() {
20843
+ clearInterval(this.$pollSizeChangesTimer);
20844
+ if (this.$measureNode)
20845
+ this.$measureNode.parentNode.removeChild(this.$measureNode);
20846
+ delete this.$measureNode;
20847
+ };
20848
+
20849
+ }).call(Text.prototype);
20850
+
20851
+ exports.Text = Text;
20852
+
20853
+ });
20854
+
20855
+ ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) {
20856
+ "use strict";
20857
+
20858
+ var dom = acequire("../lib/dom");
20859
+ var IE8;
20860
+
20861
+ var Cursor = function(parentEl) {
20862
+ this.element = dom.createElement("div");
20863
+ this.element.className = "ace_layer ace_cursor-layer";
20864
+ parentEl.appendChild(this.element);
20865
+
20866
+ if (IE8 === undefined)
20867
+ IE8 = "opacity" in this.element;
20868
+
20869
+ this.isVisible = false;
20870
+ this.isBlinking = true;
20871
+ this.blinkInterval = 1000;
20872
+ this.smoothBlinking = false;
20873
+
20874
+ this.cursors = [];
20875
+ this.cursor = this.addCursor();
20876
+ dom.addCssClass(this.element, "ace_hidden-cursors");
20877
+ this.$updateCursors = this.$updateVisibility.bind(this);
20878
+ };
20879
+
20880
+ (function() {
20881
+
20882
+ this.$updateVisibility = function(val) {
20883
+ var cursors = this.cursors;
20884
+ for (var i = cursors.length; i--; )
20885
+ cursors[i].style.visibility = val ? "" : "hidden";
20886
+ };
20887
+ this.$updateOpacity = function(val) {
20888
+ var cursors = this.cursors;
20889
+ for (var i = cursors.length; i--; )
20890
+ cursors[i].style.opacity = val ? "" : "0";
20891
+ };
20892
+
20893
+
20894
+ this.$padding = 0;
20895
+ this.setPadding = function(padding) {
20896
+ this.$padding = padding;
20897
+ };
20898
+
20899
+ this.setSession = function(session) {
20900
+ this.session = session;
20901
+ };
20902
+
20903
+ this.setBlinking = function(blinking) {
20904
+ if (blinking != this.isBlinking){
20905
+ this.isBlinking = blinking;
20906
+ this.restartTimer();
20907
+ }
20908
+ };
20909
+
20910
+ this.setBlinkInterval = function(blinkInterval) {
20911
+ if (blinkInterval != this.blinkInterval){
20912
+ this.blinkInterval = blinkInterval;
20913
+ this.restartTimer();
20914
+ }
20915
+ };
20916
+
20917
+ this.setSmoothBlinking = function(smoothBlinking) {
20918
+ if (smoothBlinking != this.smoothBlinking && !IE8) {
20919
+ this.smoothBlinking = smoothBlinking;
20920
+ dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
20921
+ this.$updateCursors(true);
20922
+ this.$updateCursors = (smoothBlinking
20923
+ ? this.$updateOpacity
20924
+ : this.$updateVisibility).bind(this);
20925
+ this.restartTimer();
20926
+ }
20927
+ };
20928
+
20929
+ this.addCursor = function() {
20930
+ var el = dom.createElement("div");
20931
+ el.className = "ace_cursor";
20932
+ this.element.appendChild(el);
20933
+ this.cursors.push(el);
20934
+ return el;
20935
+ };
20936
+
20937
+ this.removeCursor = function() {
20938
+ if (this.cursors.length > 1) {
20939
+ var el = this.cursors.pop();
20940
+ el.parentNode.removeChild(el);
20941
+ return el;
20942
+ }
20943
+ };
20944
+
20945
+ this.hideCursor = function() {
20946
+ this.isVisible = false;
20947
+ dom.addCssClass(this.element, "ace_hidden-cursors");
20948
+ this.restartTimer();
20949
+ };
20950
+
20951
+ this.showCursor = function() {
20952
+ this.isVisible = true;
20953
+ dom.removeCssClass(this.element, "ace_hidden-cursors");
20954
+ this.restartTimer();
20955
+ };
20956
+
20957
+ this.restartTimer = function() {
20958
+ var update = this.$updateCursors;
20959
+ clearInterval(this.intervalId);
20960
+ clearTimeout(this.timeoutId);
20961
+ if (this.smoothBlinking) {
20962
+ dom.removeCssClass(this.element, "ace_smooth-blinking");
20963
+ }
20964
+
20965
+ update(true);
20966
+
20967
+ if (!this.isBlinking || !this.blinkInterval || !this.isVisible)
20968
+ return;
20969
+
20970
+ if (this.smoothBlinking) {
20971
+ setTimeout(function(){
20972
+ dom.addCssClass(this.element, "ace_smooth-blinking");
20973
+ }.bind(this));
20974
+ }
20975
+
20976
+ var blink = function(){
20977
+ this.timeoutId = setTimeout(function() {
20978
+ update(false);
20979
+ }, 0.6 * this.blinkInterval);
20980
+ }.bind(this);
20981
+
20982
+ this.intervalId = setInterval(function() {
20983
+ update(true);
20984
+ blink();
20985
+ }, this.blinkInterval);
20986
+
20987
+ blink();
20988
+ };
20989
+
20990
+ this.getPixelPosition = function(position, onScreen) {
20991
+ if (!this.config || !this.session)
20992
+ return {left : 0, top : 0};
20993
+
20994
+ if (!position)
20995
+ position = this.session.selection.getCursor();
20996
+ var pos = this.session.documentToScreenPosition(position);
20997
+ var cursorLeft = this.$padding + pos.column * this.config.characterWidth;
20998
+ var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
20999
+ this.config.lineHeight;
21000
+
21001
+ return {left : cursorLeft, top : cursorTop};
21002
+ };
21003
+
21004
+ this.update = function(config) {
21005
+ this.config = config;
21006
+
21007
+ var selections = this.session.$selectionMarkers;
21008
+ var i = 0, cursorIndex = 0;
21009
+
21010
+ if (selections === undefined || selections.length === 0){
21011
+ selections = [{cursor: null}];
21012
+ }
21013
+
21014
+ for (var i = 0, n = selections.length; i < n; i++) {
21015
+ var pixelPos = this.getPixelPosition(selections[i].cursor, true);
21016
+ if ((pixelPos.top > config.height + config.offset ||
21017
+ pixelPos.top < 0) && i > 1) {
21018
+ continue;
21019
+ }
21020
+
21021
+ var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
21022
+
21023
+ style.left = pixelPos.left + "px";
21024
+ style.top = pixelPos.top + "px";
21025
+ style.width = config.characterWidth + "px";
21026
+ style.height = config.lineHeight + "px";
21027
+ }
21028
+ while (this.cursors.length > cursorIndex)
21029
+ this.removeCursor();
21030
+
21031
+ var overwrite = this.session.getOverwrite();
21032
+ this.$setOverwrite(overwrite);
21033
+ this.$pixelPos = pixelPos;
21034
+ this.restartTimer();
21035
+ };
21036
+
21037
+ this.$setOverwrite = function(overwrite) {
21038
+ if (overwrite != this.overwrite) {
21039
+ this.overwrite = overwrite;
21040
+ if (overwrite)
21041
+ dom.addCssClass(this.element, "ace_overwrite-cursors");
21042
+ else
21043
+ dom.removeCssClass(this.element, "ace_overwrite-cursors");
21044
+ }
21045
+ };
21046
+
21047
+ this.destroy = function() {
21048
+ clearInterval(this.intervalId);
21049
+ clearTimeout(this.timeoutId);
21050
+ };
21051
+
21052
+ }).call(Cursor.prototype);
21053
+
21054
+ exports.Cursor = Cursor;
21055
+
21056
+ });
21057
+
21058
+ ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(acequire, exports, module) {
21059
+ "use strict";
21060
+
21061
+ var oop = acequire("./lib/oop");
21062
+ var dom = acequire("./lib/dom");
21063
+ var event = acequire("./lib/event");
21064
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
21065
+ var ScrollBar = function(parent) {
21066
+ this.element = dom.createElement("div");
21067
+ this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix;
21068
+
21069
+ this.inner = dom.createElement("div");
21070
+ this.inner.className = "ace_scrollbar-inner";
21071
+ this.element.appendChild(this.inner);
21072
+
21073
+ parent.appendChild(this.element);
21074
+
21075
+ this.setVisible(false);
21076
+ this.skipEvent = false;
21077
+
21078
+ event.addListener(this.element, "scroll", this.onScroll.bind(this));
21079
+ event.addListener(this.element, "mousedown", event.preventDefault);
21080
+ };
21081
+
21082
+ (function() {
21083
+ oop.implement(this, EventEmitter);
21084
+
21085
+ this.setVisible = function(isVisible) {
21086
+ this.element.style.display = isVisible ? "" : "none";
21087
+ this.isVisible = isVisible;
21088
+ };
21089
+ }).call(ScrollBar.prototype);
21090
+ var VScrollBar = function(parent, renderer) {
21091
+ ScrollBar.call(this, parent);
21092
+ this.scrollTop = 0;
21093
+ renderer.$scrollbarWidth =
21094
+ this.width = dom.scrollbarWidth(parent.ownerDocument);
21095
+ this.inner.style.width =
21096
+ this.element.style.width = (this.width || 15) + 5 + "px";
21097
+ };
21098
+
21099
+ oop.inherits(VScrollBar, ScrollBar);
21100
+
21101
+ (function() {
21102
+
21103
+ this.classSuffix = '-v';
21104
+ this.onScroll = function() {
21105
+ if (!this.skipEvent) {
21106
+ this.scrollTop = this.element.scrollTop;
21107
+ this._emit("scroll", {data: this.scrollTop});
21108
+ }
21109
+ this.skipEvent = false;
21110
+ };
21111
+ this.getWidth = function() {
21112
+ return this.isVisible ? this.width : 0;
21113
+ };
21114
+ this.setHeight = function(height) {
21115
+ this.element.style.height = height + "px";
21116
+ };
21117
+ this.setInnerHeight = function(height) {
21118
+ this.inner.style.height = height + "px";
21119
+ };
21120
+ this.setScrollHeight = function(height) {
21121
+ this.inner.style.height = height + "px";
21122
+ };
21123
+ this.setScrollTop = function(scrollTop) {
21124
+ if (this.scrollTop != scrollTop) {
21125
+ this.skipEvent = true;
21126
+ this.scrollTop = this.element.scrollTop = scrollTop;
21127
+ }
21128
+ };
21129
+
21130
+ }).call(VScrollBar.prototype);
21131
+ var HScrollBar = function(parent, renderer) {
21132
+ ScrollBar.call(this, parent);
21133
+ this.scrollLeft = 0;
21134
+ this.height = renderer.$scrollbarWidth;
21135
+ this.inner.style.height =
21136
+ this.element.style.height = (this.height || 15) + 5 + "px";
21137
+ };
21138
+
21139
+ oop.inherits(HScrollBar, ScrollBar);
21140
+
21141
+ (function() {
21142
+
21143
+ this.classSuffix = '-h';
21144
+ this.onScroll = function() {
21145
+ if (!this.skipEvent) {
21146
+ this.scrollLeft = this.element.scrollLeft;
21147
+ this._emit("scroll", {data: this.scrollLeft});
21148
+ }
21149
+ this.skipEvent = false;
21150
+ };
21151
+ this.getHeight = function() {
21152
+ return this.isVisible ? this.height : 0;
21153
+ };
21154
+ this.setWidth = function(width) {
21155
+ this.element.style.width = width + "px";
21156
+ };
21157
+ this.setInnerWidth = function(width) {
21158
+ this.inner.style.width = width + "px";
21159
+ };
21160
+ this.setScrollWidth = function(width) {
21161
+ this.inner.style.width = width + "px";
21162
+ };
21163
+ this.setScrollLeft = function(scrollLeft) {
21164
+ if (this.scrollLeft != scrollLeft) {
21165
+ this.skipEvent = true;
21166
+ this.scrollLeft = this.element.scrollLeft = scrollLeft;
21167
+ }
21168
+ };
21169
+
21170
+ }).call(HScrollBar.prototype);
21171
+
21172
+
21173
+ exports.ScrollBar = VScrollBar; // backward compatibility
21174
+ exports.ScrollBarV = VScrollBar; // backward compatibility
21175
+ exports.ScrollBarH = HScrollBar; // backward compatibility
21176
+
21177
+ exports.VScrollBar = VScrollBar;
21178
+ exports.HScrollBar = HScrollBar;
21179
+ });
21180
+
21181
+ ace.define("ace/renderloop",["require","exports","module","ace/lib/event"], function(acequire, exports, module) {
21182
+ "use strict";
21183
+
21184
+ var event = acequire("./lib/event");
21185
+
21186
+
21187
+ var RenderLoop = function(onRender, win) {
21188
+ this.onRender = onRender;
21189
+ this.pending = false;
21190
+ this.changes = 0;
21191
+ this.window = win || window;
21192
+ };
21193
+
21194
+ (function() {
21195
+
21196
+
21197
+ this.schedule = function(change) {
21198
+ this.changes = this.changes | change;
21199
+ if (!this.pending && this.changes) {
21200
+ this.pending = true;
21201
+ var _self = this;
21202
+ event.nextFrame(function() {
21203
+ _self.pending = false;
21204
+ var changes;
21205
+ while (changes = _self.changes) {
21206
+ _self.changes = 0;
21207
+ _self.onRender(changes);
21208
+ }
21209
+ }, this.window);
21210
+ }
21211
+ };
21212
+
21213
+ }).call(RenderLoop.prototype);
21214
+
21215
+ exports.RenderLoop = RenderLoop;
21216
+ });
21217
+
21218
+ ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) {
21219
+
21220
+ var oop = acequire("../lib/oop");
21221
+ var dom = acequire("../lib/dom");
21222
+ var lang = acequire("../lib/lang");
21223
+ var useragent = acequire("../lib/useragent");
21224
+ var EventEmitter = acequire("../lib/event_emitter").EventEmitter;
21225
+
21226
+ var CHAR_COUNT = 0;
21227
+
21228
+ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
21229
+ this.el = dom.createElement("div");
21230
+ this.$setMeasureNodeStyles(this.el.style, true);
21231
+
21232
+ this.$main = dom.createElement("div");
21233
+ this.$setMeasureNodeStyles(this.$main.style);
21234
+
21235
+ this.$measureNode = dom.createElement("div");
21236
+ this.$setMeasureNodeStyles(this.$measureNode.style);
21237
+
21238
+
21239
+ this.el.appendChild(this.$main);
21240
+ this.el.appendChild(this.$measureNode);
21241
+ parentEl.appendChild(this.el);
21242
+
21243
+ if (!CHAR_COUNT)
21244
+ this.$testFractionalRect();
21245
+ this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT);
21246
+
21247
+ this.$characterSize = {width: 0, height: 0};
21248
+ this.checkForSizeChanges();
21249
+ };
21250
+
21251
+ (function() {
21252
+
21253
+ oop.implement(this, EventEmitter);
21254
+
21255
+ this.$characterSize = {width: 0, height: 0};
21256
+
21257
+ this.$testFractionalRect = function() {
21258
+ var el = dom.createElement("div");
21259
+ this.$setMeasureNodeStyles(el.style);
21260
+ el.style.width = "0.2px";
21261
+ document.documentElement.appendChild(el);
21262
+ var w = el.getBoundingClientRect().width;
21263
+ if (w > 0 && w < 1)
21264
+ CHAR_COUNT = 50;
21265
+ else
21266
+ CHAR_COUNT = 100;
21267
+ el.parentNode.removeChild(el);
21268
+ };
21269
+
21270
+ this.$setMeasureNodeStyles = function(style, isRoot) {
21271
+ style.width = style.height = "auto";
21272
+ style.left = style.top = "-100px";
21273
+ style.visibility = "hidden";
21274
+ style.position = "fixed";
21275
+ style.whiteSpace = "pre";
21276
+
21277
+ if (useragent.isIE < 8) {
21278
+ style["font-family"] = "inherit";
21279
+ } else {
21280
+ style.font = "inherit";
21281
+ }
21282
+ style.overflow = isRoot ? "hidden" : "visible";
21283
+ };
21284
+
21285
+ this.checkForSizeChanges = function() {
21286
+ var size = this.$measureSizes();
21287
+ if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
21288
+ this.$measureNode.style.fontWeight = "bold";
21289
+ var boldSize = this.$measureSizes();
21290
+ this.$measureNode.style.fontWeight = "";
21291
+ this.$characterSize = size;
21292
+ this.charSizes = Object.create(null);
21293
+ this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
21294
+ this._emit("changeCharacterSize", {data: size});
21295
+ }
21296
+ };
21297
+
21298
+ this.$pollSizeChanges = function() {
21299
+ if (this.$pollSizeChangesTimer)
21300
+ return this.$pollSizeChangesTimer;
21301
+ var self = this;
21302
+ return this.$pollSizeChangesTimer = setInterval(function() {
21303
+ self.checkForSizeChanges();
21304
+ }, 500);
21305
+ };
21306
+
21307
+ this.setPolling = function(val) {
21308
+ if (val) {
21309
+ this.$pollSizeChanges();
21310
+ } else {
21311
+ if (this.$pollSizeChangesTimer)
21312
+ this.$pollSizeChangesTimer;
21313
+ }
21314
+ };
21315
+
21316
+ this.$measureSizes = function() {
21317
+ if (CHAR_COUNT === 50) {
21318
+ var rect = null;
21319
+ try {
21320
+ rect = this.$measureNode.getBoundingClientRect();
21321
+ } catch(e) {
21322
+ rect = {width: 0, height:0 };
21323
+ };
21324
+ var size = {
21325
+ height: rect.height,
21326
+ width: rect.width / CHAR_COUNT
21327
+ };
21328
+ } else {
21329
+ var size = {
21330
+ height: this.$measureNode.clientHeight,
21331
+ width: this.$measureNode.clientWidth / CHAR_COUNT
21332
+ };
21333
+ }
21334
+ if (size.width === 0 || size.height === 0)
21335
+ return null;
21336
+ return size;
21337
+ };
21338
+
21339
+ this.$measureCharWidth = function(ch) {
21340
+ this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT);
21341
+ var rect = this.$main.getBoundingClientRect();
21342
+ return rect.width / CHAR_COUNT;
21343
+ };
21344
+
21345
+ this.getCharacterWidth = function(ch) {
21346
+ var w = this.charSizes[ch];
21347
+ if (w === undefined) {
21348
+ this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
21349
+ }
21350
+ return w;
21351
+ };
21352
+
21353
+ this.destroy = function() {
21354
+ clearInterval(this.$pollSizeChangesTimer);
21355
+ if (this.el && this.el.parentNode)
21356
+ this.el.parentNode.removeChild(this.el);
21357
+ };
21358
+
21359
+ }).call(FontMetrics.prototype);
21360
+
21361
+ });
21362
+
21363
+ ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(acequire, exports, module) {
21364
+ "use strict";
21365
+
21366
+ var oop = acequire("./lib/oop");
21367
+ var dom = acequire("./lib/dom");
21368
+ var config = acequire("./config");
21369
+ var useragent = acequire("./lib/useragent");
21370
+ var GutterLayer = acequire("./layer/gutter").Gutter;
21371
+ var MarkerLayer = acequire("./layer/marker").Marker;
21372
+ var TextLayer = acequire("./layer/text").Text;
21373
+ var CursorLayer = acequire("./layer/cursor").Cursor;
21374
+ var HScrollBar = acequire("./scrollbar").HScrollBar;
21375
+ var VScrollBar = acequire("./scrollbar").VScrollBar;
21376
+ var RenderLoop = acequire("./renderloop").RenderLoop;
21377
+ var FontMetrics = acequire("./layer/font_metrics").FontMetrics;
21378
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
21379
+ var editorCss = ".ace_editor {\
21380
+ position: relative;\
21381
+ overflow: hidden;\
21382
+ font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\
21383
+ direction: ltr;\
21384
+ }\
21385
+ .ace_scroller {\
21386
+ position: absolute;\
21387
+ overflow: hidden;\
21388
+ top: 0;\
21389
+ bottom: 0;\
21390
+ background-color: inherit;\
21391
+ -ms-user-select: none;\
21392
+ -moz-user-select: none;\
21393
+ -webkit-user-select: none;\
21394
+ user-select: none;\
21395
+ cursor: text;\
21396
+ }\
21397
+ .ace_content {\
21398
+ position: absolute;\
21399
+ -moz-box-sizing: border-box;\
21400
+ -webkit-box-sizing: border-box;\
21401
+ box-sizing: border-box;\
21402
+ min-width: 100%;\
21403
+ }\
21404
+ .ace_dragging .ace_scroller:before{\
21405
+ position: absolute;\
21406
+ top: 0;\
21407
+ left: 0;\
21408
+ right: 0;\
21409
+ bottom: 0;\
21410
+ content: '';\
21411
+ background: rgba(250, 250, 250, 0.01);\
21412
+ z-index: 1000;\
21413
+ }\
21414
+ .ace_dragging.ace_dark .ace_scroller:before{\
21415
+ background: rgba(0, 0, 0, 0.01);\
21416
+ }\
21417
+ .ace_selecting, .ace_selecting * {\
21418
+ cursor: text !important;\
21419
+ }\
21420
+ .ace_gutter {\
21421
+ position: absolute;\
21422
+ overflow : hidden;\
21423
+ width: auto;\
21424
+ top: 0;\
21425
+ bottom: 0;\
21426
+ left: 0;\
21427
+ cursor: default;\
21428
+ z-index: 4;\
21429
+ -ms-user-select: none;\
21430
+ -moz-user-select: none;\
21431
+ -webkit-user-select: none;\
21432
+ user-select: none;\
21433
+ }\
21434
+ .ace_gutter-active-line {\
21435
+ position: absolute;\
21436
+ left: 0;\
21437
+ right: 0;\
21438
+ }\
21439
+ .ace_scroller.ace_scroll-left {\
21440
+ box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\
21441
+ }\
21442
+ .ace_gutter-cell {\
21443
+ padding-left: 19px;\
21444
+ padding-right: 6px;\
21445
+ background-repeat: no-repeat;\
21446
+ }\
21447
+ .ace_gutter-cell.ace_error {\
21448
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\
21449
+ background-repeat: no-repeat;\
21450
+ background-position: 2px center;\
21451
+ }\
21452
+ .ace_gutter-cell.ace_warning {\
21453
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\
21454
+ background-position: 2px center;\
21455
+ }\
21456
+ .ace_gutter-cell.ace_info {\
21457
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\
21458
+ background-position: 2px center;\
21459
+ }\
21460
+ .ace_dark .ace_gutter-cell.ace_info {\
21461
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\
21462
+ }\
21463
+ .ace_scrollbar {\
21464
+ position: absolute;\
21465
+ right: 0;\
21466
+ bottom: 0;\
21467
+ z-index: 6;\
21468
+ }\
21469
+ .ace_scrollbar-inner {\
21470
+ position: absolute;\
21471
+ cursor: text;\
21472
+ left: 0;\
21473
+ top: 0;\
21474
+ }\
21475
+ .ace_scrollbar-v{\
21476
+ overflow-x: hidden;\
21477
+ overflow-y: scroll;\
21478
+ top: 0;\
21479
+ }\
21480
+ .ace_scrollbar-h {\
21481
+ overflow-x: scroll;\
21482
+ overflow-y: hidden;\
21483
+ left: 0;\
21484
+ }\
21485
+ .ace_print-margin {\
21486
+ position: absolute;\
21487
+ height: 100%;\
21488
+ }\
21489
+ .ace_text-input {\
21490
+ position: absolute;\
21491
+ z-index: 0;\
21492
+ width: 0.5em;\
21493
+ height: 1em;\
21494
+ opacity: 0;\
21495
+ background: transparent;\
21496
+ -moz-appearance: none;\
21497
+ appearance: none;\
21498
+ border: none;\
21499
+ resize: none;\
21500
+ outline: none;\
21501
+ overflow: hidden;\
21502
+ font: inherit;\
21503
+ padding: 0 1px;\
21504
+ margin: 0 -1px;\
21505
+ text-indent: -1em;\
21506
+ -ms-user-select: text;\
21507
+ -moz-user-select: text;\
21508
+ -webkit-user-select: text;\
21509
+ user-select: text;\
21510
+ }\
21511
+ .ace_text-input.ace_composition {\
21512
+ background: inherit;\
21513
+ color: inherit;\
21514
+ z-index: 1000;\
21515
+ opacity: 1;\
21516
+ text-indent: 0;\
21517
+ }\
21518
+ .ace_layer {\
21519
+ z-index: 1;\
21520
+ position: absolute;\
21521
+ overflow: hidden;\
21522
+ white-space: pre;\
21523
+ height: 100%;\
21524
+ width: 100%;\
21525
+ -moz-box-sizing: border-box;\
21526
+ -webkit-box-sizing: border-box;\
21527
+ box-sizing: border-box;\
21528
+ pointer-events: none;\
21529
+ }\
21530
+ .ace_gutter-layer {\
21531
+ position: relative;\
21532
+ width: auto;\
21533
+ text-align: right;\
21534
+ pointer-events: auto;\
21535
+ }\
21536
+ .ace_text-layer {\
21537
+ font: inherit !important;\
21538
+ }\
21539
+ .ace_cjk {\
21540
+ display: inline-block;\
21541
+ text-align: center;\
21542
+ }\
21543
+ .ace_cursor-layer {\
21544
+ z-index: 4;\
21545
+ }\
21546
+ .ace_cursor {\
21547
+ z-index: 4;\
21548
+ position: absolute;\
21549
+ -moz-box-sizing: border-box;\
21550
+ -webkit-box-sizing: border-box;\
21551
+ box-sizing: border-box;\
21552
+ border-left: 2px solid\
21553
+ }\
21554
+ .ace_slim-cursors .ace_cursor {\
21555
+ border-left-width: 1px;\
21556
+ }\
21557
+ .ace_overwrite-cursors .ace_cursor {\
21558
+ border-left-width: 0;\
21559
+ border-bottom: 1px solid;\
21560
+ }\
21561
+ .ace_hidden-cursors .ace_cursor {\
21562
+ opacity: 0.2;\
21563
+ }\
21564
+ .ace_smooth-blinking .ace_cursor {\
21565
+ -webkit-transition: opacity 0.18s;\
21566
+ transition: opacity 0.18s;\
21567
+ }\
21568
+ .ace_editor.ace_multiselect .ace_cursor {\
21569
+ border-left-width: 1px;\
21570
+ }\
21571
+ .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\
21572
+ position: absolute;\
21573
+ z-index: 3;\
21574
+ }\
21575
+ .ace_marker-layer .ace_selection {\
21576
+ position: absolute;\
21577
+ z-index: 5;\
21578
+ }\
21579
+ .ace_marker-layer .ace_bracket {\
21580
+ position: absolute;\
21581
+ z-index: 6;\
21582
+ }\
21583
+ .ace_marker-layer .ace_active-line {\
21584
+ position: absolute;\
21585
+ z-index: 2;\
21586
+ }\
21587
+ .ace_marker-layer .ace_selected-word {\
21588
+ position: absolute;\
21589
+ z-index: 4;\
21590
+ -moz-box-sizing: border-box;\
21591
+ -webkit-box-sizing: border-box;\
21592
+ box-sizing: border-box;\
21593
+ }\
21594
+ .ace_line .ace_fold {\
21595
+ -moz-box-sizing: border-box;\
21596
+ -webkit-box-sizing: border-box;\
21597
+ box-sizing: border-box;\
21598
+ display: inline-block;\
21599
+ height: 11px;\
21600
+ margin-top: -2px;\
21601
+ vertical-align: middle;\
21602
+ background-image:\
21603
+ url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\
21604
+ url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\
21605
+ background-repeat: no-repeat, repeat-x;\
21606
+ background-position: center center, top left;\
21607
+ color: transparent;\
21608
+ border: 1px solid black;\
21609
+ border-radius: 2px;\
21610
+ cursor: pointer;\
21611
+ pointer-events: auto;\
21612
+ }\
21613
+ .ace_dark .ace_fold {\
21614
+ }\
21615
+ .ace_fold:hover{\
21616
+ background-image:\
21617
+ url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\
21618
+ url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\
21619
+ }\
21620
+ .ace_tooltip {\
21621
+ background-color: #FFF;\
21622
+ background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\
21623
+ background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\
21624
+ border: 1px solid gray;\
21625
+ border-radius: 1px;\
21626
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\
21627
+ color: black;\
21628
+ max-width: 100%;\
21629
+ padding: 3px 4px;\
21630
+ position: fixed;\
21631
+ z-index: 999999;\
21632
+ -moz-box-sizing: border-box;\
21633
+ -webkit-box-sizing: border-box;\
21634
+ box-sizing: border-box;\
21635
+ cursor: default;\
21636
+ white-space: pre;\
21637
+ word-wrap: break-word;\
21638
+ line-height: normal;\
21639
+ font-style: normal;\
21640
+ font-weight: normal;\
21641
+ letter-spacing: normal;\
21642
+ pointer-events: none;\
21643
+ }\
21644
+ .ace_folding-enabled > .ace_gutter-cell {\
21645
+ padding-right: 13px;\
21646
+ }\
21647
+ .ace_fold-widget {\
21648
+ -moz-box-sizing: border-box;\
21649
+ -webkit-box-sizing: border-box;\
21650
+ box-sizing: border-box;\
21651
+ margin: 0 -12px 0 1px;\
21652
+ display: none;\
21653
+ width: 11px;\
21654
+ vertical-align: top;\
21655
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\
21656
+ background-repeat: no-repeat;\
21657
+ background-position: center;\
21658
+ border-radius: 3px;\
21659
+ border: 1px solid transparent;\
21660
+ cursor: pointer;\
21661
+ }\
21662
+ .ace_folding-enabled .ace_fold-widget {\
21663
+ display: inline-block; \
21664
+ }\
21665
+ .ace_fold-widget.ace_end {\
21666
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\
21667
+ }\
21668
+ .ace_fold-widget.ace_closed {\
21669
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\
21670
+ }\
21671
+ .ace_fold-widget:hover {\
21672
+ border: 1px solid rgba(0, 0, 0, 0.3);\
21673
+ background-color: rgba(255, 255, 255, 0.2);\
21674
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\
21675
+ }\
21676
+ .ace_fold-widget:active {\
21677
+ border: 1px solid rgba(0, 0, 0, 0.4);\
21678
+ background-color: rgba(0, 0, 0, 0.05);\
21679
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\
21680
+ }\
21681
+ .ace_dark .ace_fold-widget {\
21682
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\
21683
+ }\
21684
+ .ace_dark .ace_fold-widget.ace_end {\
21685
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\
21686
+ }\
21687
+ .ace_dark .ace_fold-widget.ace_closed {\
21688
+ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\
21689
+ }\
21690
+ .ace_dark .ace_fold-widget:hover {\
21691
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
21692
+ background-color: rgba(255, 255, 255, 0.1);\
21693
+ }\
21694
+ .ace_dark .ace_fold-widget:active {\
21695
+ box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
21696
+ }\
21697
+ .ace_fold-widget.ace_invalid {\
21698
+ background-color: #FFB4B4;\
21699
+ border-color: #DE5555;\
21700
+ }\
21701
+ .ace_fade-fold-widgets .ace_fold-widget {\
21702
+ -webkit-transition: opacity 0.4s ease 0.05s;\
21703
+ transition: opacity 0.4s ease 0.05s;\
21704
+ opacity: 0;\
21705
+ }\
21706
+ .ace_fade-fold-widgets:hover .ace_fold-widget {\
21707
+ -webkit-transition: opacity 0.05s ease 0.05s;\
21708
+ transition: opacity 0.05s ease 0.05s;\
21709
+ opacity:1;\
21710
+ }\
21711
+ .ace_underline {\
21712
+ text-decoration: underline;\
21713
+ }\
21714
+ .ace_bold {\
21715
+ font-weight: bold;\
21716
+ }\
21717
+ .ace_nobold .ace_bold {\
21718
+ font-weight: normal;\
21719
+ }\
21720
+ .ace_italic {\
21721
+ font-style: italic;\
21722
+ }\
21723
+ .ace_error-marker {\
21724
+ background-color: rgba(255, 0, 0,0.2);\
21725
+ position: absolute;\
21726
+ z-index: 9;\
21727
+ }\
21728
+ .ace_highlight-marker {\
21729
+ background-color: rgba(255, 255, 0,0.2);\
21730
+ position: absolute;\
21731
+ z-index: 8;\
21732
+ }\
21733
+ ";
21734
+
21735
+ dom.importCssString(editorCss, "ace_editor");
21736
+
21737
+ var VirtualRenderer = function(container, theme) {
21738
+ var _self = this;
21739
+
21740
+ this.container = container || dom.createElement("div");
21741
+ this.$keepTextAreaAtCursor = !useragent.isOldIE;
21742
+
21743
+ dom.addCssClass(this.container, "ace_editor");
21744
+
21745
+ this.setTheme(theme);
21746
+
21747
+ this.$gutter = dom.createElement("div");
21748
+ this.$gutter.className = "ace_gutter";
21749
+ this.container.appendChild(this.$gutter);
21750
+
21751
+ this.scroller = dom.createElement("div");
21752
+ this.scroller.className = "ace_scroller";
21753
+ this.container.appendChild(this.scroller);
21754
+
21755
+ this.content = dom.createElement("div");
21756
+ this.content.className = "ace_content";
21757
+ this.scroller.appendChild(this.content);
21758
+
21759
+ this.$gutterLayer = new GutterLayer(this.$gutter);
21760
+ this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this));
21761
+
21762
+ this.$markerBack = new MarkerLayer(this.content);
21763
+
21764
+ var textLayer = this.$textLayer = new TextLayer(this.content);
21765
+ this.canvas = textLayer.element;
21766
+
21767
+ this.$markerFront = new MarkerLayer(this.content);
21768
+
21769
+ this.$cursorLayer = new CursorLayer(this.content);
21770
+ this.$horizScroll = false;
21771
+ this.$vScroll = false;
21772
+
21773
+ this.scrollBar =
21774
+ this.scrollBarV = new VScrollBar(this.container, this);
21775
+ this.scrollBarH = new HScrollBar(this.container, this);
21776
+ this.scrollBarV.addEventListener("scroll", function(e) {
21777
+ if (!_self.$scrollAnimation)
21778
+ _self.session.setScrollTop(e.data - _self.scrollMargin.top);
21779
+ });
21780
+ this.scrollBarH.addEventListener("scroll", function(e) {
21781
+ if (!_self.$scrollAnimation)
21782
+ _self.session.setScrollLeft(e.data - _self.scrollMargin.left);
21783
+ });
21784
+
21785
+ this.scrollTop = 0;
21786
+ this.scrollLeft = 0;
21787
+
21788
+ this.cursorPos = {
21789
+ row : 0,
21790
+ column : 0
21791
+ };
21792
+
21793
+ this.$fontMetrics = new FontMetrics(this.container, 500);
21794
+ this.$textLayer.$setFontMetrics(this.$fontMetrics);
21795
+ this.$textLayer.addEventListener("changeCharacterSize", function(e) {
21796
+ _self.updateCharacterSize();
21797
+ _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height);
21798
+ _self._signal("changeCharacterSize", e);
21799
+ });
21800
+
21801
+ this.$size = {
21802
+ width: 0,
21803
+ height: 0,
21804
+ scrollerHeight: 0,
21805
+ scrollerWidth: 0,
21806
+ $dirty: true
21807
+ };
21808
+
21809
+ this.layerConfig = {
21810
+ width : 1,
21811
+ padding : 0,
21812
+ firstRow : 0,
21813
+ firstRowScreen: 0,
21814
+ lastRow : 0,
21815
+ lineHeight : 0,
21816
+ characterWidth : 0,
21817
+ minHeight : 1,
21818
+ maxHeight : 1,
21819
+ offset : 0,
21820
+ height : 1,
21821
+ gutterOffset: 1
21822
+ };
21823
+
21824
+ this.scrollMargin = {
21825
+ left: 0,
21826
+ right: 0,
21827
+ top: 0,
21828
+ bottom: 0,
21829
+ v: 0,
21830
+ h: 0
21831
+ };
21832
+
21833
+ this.$loop = new RenderLoop(
21834
+ this.$renderChanges.bind(this),
21835
+ this.container.ownerDocument.defaultView
21836
+ );
21837
+ this.$loop.schedule(this.CHANGE_FULL);
21838
+
21839
+ this.updateCharacterSize();
21840
+ this.setPadding(4);
21841
+ config.resetOptions(this);
21842
+ config._emit("renderer", this);
21843
+ };
21844
+
21845
+ (function() {
21846
+
21847
+ this.CHANGE_CURSOR = 1;
21848
+ this.CHANGE_MARKER = 2;
21849
+ this.CHANGE_GUTTER = 4;
21850
+ this.CHANGE_SCROLL = 8;
21851
+ this.CHANGE_LINES = 16;
21852
+ this.CHANGE_TEXT = 32;
21853
+ this.CHANGE_SIZE = 64;
21854
+ this.CHANGE_MARKER_BACK = 128;
21855
+ this.CHANGE_MARKER_FRONT = 256;
21856
+ this.CHANGE_FULL = 512;
21857
+ this.CHANGE_H_SCROLL = 1024;
21858
+
21859
+ oop.implement(this, EventEmitter);
21860
+
21861
+ this.updateCharacterSize = function() {
21862
+ if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) {
21863
+ this.$allowBoldFonts = this.$textLayer.allowBoldFonts;
21864
+ this.setStyle("ace_nobold", !this.$allowBoldFonts);
21865
+ }
21866
+
21867
+ this.layerConfig.characterWidth =
21868
+ this.characterWidth = this.$textLayer.getCharacterWidth();
21869
+ this.layerConfig.lineHeight =
21870
+ this.lineHeight = this.$textLayer.getLineHeight();
21871
+ this.$updatePrintMargin();
21872
+ };
21873
+ this.setSession = function(session) {
21874
+ if (this.session)
21875
+ this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode);
21876
+
21877
+ this.session = session;
21878
+ if (session && this.scrollMargin.top && session.getScrollTop() <= 0)
21879
+ session.setScrollTop(-this.scrollMargin.top);
21880
+
21881
+ this.$cursorLayer.setSession(session);
21882
+ this.$markerBack.setSession(session);
21883
+ this.$markerFront.setSession(session);
21884
+ this.$gutterLayer.setSession(session);
21885
+ this.$textLayer.setSession(session);
21886
+ if (!session)
21887
+ return;
21888
+
21889
+ this.$loop.schedule(this.CHANGE_FULL);
21890
+ this.session.$setFontMetrics(this.$fontMetrics);
21891
+
21892
+ this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this);
21893
+ this.onChangeNewLineMode()
21894
+ this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode);
21895
+ };
21896
+ this.updateLines = function(firstRow, lastRow, force) {
21897
+ if (lastRow === undefined)
21898
+ lastRow = Infinity;
21899
+
21900
+ if (!this.$changedLines) {
21901
+ this.$changedLines = {
21902
+ firstRow: firstRow,
21903
+ lastRow: lastRow
21904
+ };
21905
+ }
21906
+ else {
21907
+ if (this.$changedLines.firstRow > firstRow)
21908
+ this.$changedLines.firstRow = firstRow;
21909
+
21910
+ if (this.$changedLines.lastRow < lastRow)
21911
+ this.$changedLines.lastRow = lastRow;
21912
+ }
21913
+ if (this.$changedLines.lastRow < this.layerConfig.firstRow) {
21914
+ if (force)
21915
+ this.$changedLines.lastRow = this.layerConfig.lastRow;
21916
+ else
21917
+ return;
21918
+ }
21919
+ if (this.$changedLines.firstRow > this.layerConfig.lastRow)
21920
+ return;
21921
+ this.$loop.schedule(this.CHANGE_LINES);
21922
+ };
21923
+
21924
+ this.onChangeNewLineMode = function() {
21925
+ this.$loop.schedule(this.CHANGE_TEXT);
21926
+ this.$textLayer.$updateEolChar();
21927
+ };
21928
+
21929
+ this.onChangeTabSize = function() {
21930
+ this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER);
21931
+ this.$textLayer.onChangeTabSize();
21932
+ };
21933
+ this.updateText = function() {
21934
+ this.$loop.schedule(this.CHANGE_TEXT);
21935
+ };
21936
+ this.updateFull = function(force) {
21937
+ if (force)
21938
+ this.$renderChanges(this.CHANGE_FULL, true);
21939
+ else
21940
+ this.$loop.schedule(this.CHANGE_FULL);
21941
+ };
21942
+ this.updateFontSize = function() {
21943
+ this.$textLayer.checkForSizeChanges();
21944
+ };
21945
+
21946
+ this.$changes = 0;
21947
+ this.$updateSizeAsync = function() {
21948
+ if (this.$loop.pending)
21949
+ this.$size.$dirty = true;
21950
+ else
21951
+ this.onResize();
21952
+ };
21953
+ this.onResize = function(force, gutterWidth, width, height) {
21954
+ if (this.resizing > 2)
21955
+ return;
21956
+ else if (this.resizing > 0)
21957
+ this.resizing++;
21958
+ else
21959
+ this.resizing = force ? 1 : 0;
21960
+ var el = this.container;
21961
+ if (!height)
21962
+ height = el.clientHeight || el.scrollHeight;
21963
+ if (!width)
21964
+ width = el.clientWidth || el.scrollWidth;
21965
+ var changes = this.$updateCachedSize(force, gutterWidth, width, height);
21966
+
21967
+
21968
+ if (!this.$size.scrollerHeight || (!width && !height))
21969
+ return this.resizing = 0;
21970
+
21971
+ if (force)
21972
+ this.$gutterLayer.$padding = null;
21973
+
21974
+ if (force)
21975
+ this.$renderChanges(changes | this.$changes, true);
21976
+ else
21977
+ this.$loop.schedule(changes | this.$changes);
21978
+
21979
+ if (this.resizing)
21980
+ this.resizing = 0;
21981
+ };
21982
+
21983
+ this.$updateCachedSize = function(force, gutterWidth, width, height) {
21984
+ height -= (this.$extraHeight || 0);
21985
+ var changes = 0;
21986
+ var size = this.$size;
21987
+ var oldSize = {
21988
+ width: size.width,
21989
+ height: size.height,
21990
+ scrollerHeight: size.scrollerHeight,
21991
+ scrollerWidth: size.scrollerWidth
21992
+ };
21993
+ if (height && (force || size.height != height)) {
21994
+ size.height = height;
21995
+ changes |= this.CHANGE_SIZE;
21996
+
21997
+ size.scrollerHeight = size.height;
21998
+ if (this.$horizScroll)
21999
+ size.scrollerHeight -= this.scrollBarH.getHeight();
22000
+ this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px";
22001
+
22002
+ changes = changes | this.CHANGE_SCROLL;
22003
+ }
22004
+
22005
+ if (width && (force || size.width != width)) {
22006
+ changes |= this.CHANGE_SIZE;
22007
+ size.width = width;
22008
+
22009
+ if (gutterWidth == null)
22010
+ gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
22011
+
22012
+ this.gutterWidth = gutterWidth;
22013
+
22014
+ this.scrollBarH.element.style.left =
22015
+ this.scroller.style.left = gutterWidth + "px";
22016
+ size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth());
22017
+
22018
+ this.scrollBarH.element.style.right =
22019
+ this.scroller.style.right = this.scrollBarV.getWidth() + "px";
22020
+ this.scroller.style.bottom = this.scrollBarH.getHeight() + "px";
22021
+
22022
+ if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
22023
+ changes |= this.CHANGE_FULL;
22024
+ }
22025
+
22026
+ size.$dirty = !width || !height;
22027
+
22028
+ if (changes)
22029
+ this._signal("resize", oldSize);
22030
+
22031
+ return changes;
22032
+ };
22033
+
22034
+ this.onGutterResize = function() {
22035
+ var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
22036
+ if (gutterWidth != this.gutterWidth)
22037
+ this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height);
22038
+
22039
+ if (this.session.getUseWrapMode() && this.adjustWrapLimit()) {
22040
+ this.$loop.schedule(this.CHANGE_FULL);
22041
+ } else if (this.$size.$dirty) {
22042
+ this.$loop.schedule(this.CHANGE_FULL);
22043
+ } else {
22044
+ this.$computeLayerConfig();
22045
+ this.$loop.schedule(this.CHANGE_MARKER);
22046
+ }
22047
+ };
22048
+ this.adjustWrapLimit = function() {
22049
+ var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
22050
+ var limit = Math.floor(availableWidth / this.characterWidth);
22051
+ return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn);
22052
+ };
22053
+ this.setAnimatedScroll = function(shouldAnimate){
22054
+ this.setOption("animatedScroll", shouldAnimate);
22055
+ };
22056
+ this.getAnimatedScroll = function() {
22057
+ return this.$animatedScroll;
22058
+ };
22059
+ this.setShowInvisibles = function(showInvisibles) {
22060
+ this.setOption("showInvisibles", showInvisibles);
22061
+ };
22062
+ this.getShowInvisibles = function() {
22063
+ return this.getOption("showInvisibles");
22064
+ };
22065
+ this.getDisplayIndentGuides = function() {
22066
+ return this.getOption("displayIndentGuides");
22067
+ };
22068
+
22069
+ this.setDisplayIndentGuides = function(display) {
22070
+ this.setOption("displayIndentGuides", display);
22071
+ };
22072
+ this.setShowPrintMargin = function(showPrintMargin) {
22073
+ this.setOption("showPrintMargin", showPrintMargin);
22074
+ };
22075
+ this.getShowPrintMargin = function() {
22076
+ return this.getOption("showPrintMargin");
22077
+ };
22078
+ this.setPrintMarginColumn = function(showPrintMargin) {
22079
+ this.setOption("printMarginColumn", showPrintMargin);
22080
+ };
22081
+ this.getPrintMarginColumn = function() {
22082
+ return this.getOption("printMarginColumn");
22083
+ };
22084
+ this.getShowGutter = function(){
22085
+ return this.getOption("showGutter");
22086
+ };
22087
+ this.setShowGutter = function(show){
22088
+ return this.setOption("showGutter", show);
22089
+ };
22090
+
22091
+ this.getFadeFoldWidgets = function(){
22092
+ return this.getOption("fadeFoldWidgets")
22093
+ };
22094
+
22095
+ this.setFadeFoldWidgets = function(show) {
22096
+ this.setOption("fadeFoldWidgets", show);
22097
+ };
22098
+
22099
+ this.setHighlightGutterLine = function(shouldHighlight) {
22100
+ this.setOption("highlightGutterLine", shouldHighlight);
22101
+ };
22102
+
22103
+ this.getHighlightGutterLine = function() {
22104
+ return this.getOption("highlightGutterLine");
22105
+ };
22106
+
22107
+ this.$updateGutterLineHighlight = function() {
22108
+ var pos = this.$cursorLayer.$pixelPos;
22109
+ var height = this.layerConfig.lineHeight;
22110
+ if (this.session.getUseWrapMode()) {
22111
+ var cursor = this.session.selection.getCursor();
22112
+ cursor.column = 0;
22113
+ pos = this.$cursorLayer.getPixelPosition(cursor, true);
22114
+ height *= this.session.getRowLength(cursor.row);
22115
+ }
22116
+ this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px";
22117
+ this.$gutterLineHighlight.style.height = height + "px";
22118
+ };
22119
+
22120
+ this.$updatePrintMargin = function() {
22121
+ if (!this.$showPrintMargin && !this.$printMarginEl)
22122
+ return;
22123
+
22124
+ if (!this.$printMarginEl) {
22125
+ var containerEl = dom.createElement("div");
22126
+ containerEl.className = "ace_layer ace_print-margin-layer";
22127
+ this.$printMarginEl = dom.createElement("div");
22128
+ this.$printMarginEl.className = "ace_print-margin";
22129
+ containerEl.appendChild(this.$printMarginEl);
22130
+ this.content.insertBefore(containerEl, this.content.firstChild);
22131
+ }
22132
+
22133
+ var style = this.$printMarginEl.style;
22134
+ style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px";
22135
+ style.visibility = this.$showPrintMargin ? "visible" : "hidden";
22136
+
22137
+ if (this.session && this.session.$wrap == -1)
22138
+ this.adjustWrapLimit();
22139
+ };
22140
+ this.getContainerElement = function() {
22141
+ return this.container;
22142
+ };
22143
+ this.getMouseEventTarget = function() {
22144
+ return this.content;
22145
+ };
22146
+ this.getTextAreaContainer = function() {
22147
+ return this.container;
22148
+ };
22149
+ this.$moveTextAreaToCursor = function() {
22150
+ if (!this.$keepTextAreaAtCursor)
22151
+ return;
22152
+ var config = this.layerConfig;
22153
+ var posTop = this.$cursorLayer.$pixelPos.top;
22154
+ var posLeft = this.$cursorLayer.$pixelPos.left;
22155
+ posTop -= config.offset;
22156
+
22157
+ var h = this.lineHeight;
22158
+ if (posTop < 0 || posTop > config.height - h)
22159
+ return;
22160
+
22161
+ var w = this.characterWidth;
22162
+ if (this.$composition) {
22163
+ var val = this.textarea.value.replace(/^\x01+/, "");
22164
+ w *= (this.session.$getStringScreenWidth(val)[0]+2);
22165
+ h += 2;
22166
+ }
22167
+ posLeft -= this.scrollLeft;
22168
+ if (posLeft > this.$size.scrollerWidth - w)
22169
+ posLeft = this.$size.scrollerWidth - w;
22170
+
22171
+ posLeft += this.gutterWidth;
22172
+
22173
+ this.textarea.style.height = h + "px";
22174
+ this.textarea.style.width = w + "px";
22175
+ this.textarea.style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px";
22176
+ this.textarea.style.top = Math.min(posTop, this.$size.height - h) + "px";
22177
+ };
22178
+ this.getFirstVisibleRow = function() {
22179
+ return this.layerConfig.firstRow;
22180
+ };
22181
+ this.getFirstFullyVisibleRow = function() {
22182
+ return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
22183
+ };
22184
+ this.getLastFullyVisibleRow = function() {
22185
+ var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight);
22186
+ return this.layerConfig.firstRow - 1 + flint;
22187
+ };
22188
+ this.getLastVisibleRow = function() {
22189
+ return this.layerConfig.lastRow;
22190
+ };
22191
+
22192
+ this.$padding = null;
22193
+ this.setPadding = function(padding) {
22194
+ this.$padding = padding;
22195
+ this.$textLayer.setPadding(padding);
22196
+ this.$cursorLayer.setPadding(padding);
22197
+ this.$markerFront.setPadding(padding);
22198
+ this.$markerBack.setPadding(padding);
22199
+ this.$loop.schedule(this.CHANGE_FULL);
22200
+ this.$updatePrintMargin();
22201
+ };
22202
+
22203
+ this.setScrollMargin = function(top, bottom, left, right) {
22204
+ var sm = this.scrollMargin;
22205
+ sm.top = top|0;
22206
+ sm.bottom = bottom|0;
22207
+ sm.right = right|0;
22208
+ sm.left = left|0;
22209
+ sm.v = sm.top + sm.bottom;
22210
+ sm.h = sm.left + sm.right;
22211
+ if (sm.top && this.scrollTop <= 0 && this.session)
22212
+ this.session.setScrollTop(-sm.top);
22213
+ this.updateFull();
22214
+ };
22215
+ this.getHScrollBarAlwaysVisible = function() {
22216
+ return this.$hScrollBarAlwaysVisible;
22217
+ };
22218
+ this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
22219
+ this.setOption("hScrollBarAlwaysVisible", alwaysVisible);
22220
+ };
22221
+ this.getVScrollBarAlwaysVisible = function() {
22222
+ return this.$hScrollBarAlwaysVisible;
22223
+ };
22224
+ this.setVScrollBarAlwaysVisible = function(alwaysVisible) {
22225
+ this.setOption("vScrollBarAlwaysVisible", alwaysVisible);
22226
+ };
22227
+
22228
+ this.$updateScrollBarV = function() {
22229
+ var scrollHeight = this.layerConfig.maxHeight;
22230
+ var scrollerHeight = this.$size.scrollerHeight;
22231
+ if (!this.$maxLines && this.$scrollPastEnd) {
22232
+ scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd;
22233
+ if (this.scrollTop > scrollHeight - scrollerHeight) {
22234
+ scrollHeight = this.scrollTop + scrollerHeight;
22235
+ this.scrollBarV.scrollTop = null;
22236
+ }
22237
+ }
22238
+ this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v);
22239
+ this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top);
22240
+ };
22241
+ this.$updateScrollBarH = function() {
22242
+ this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h);
22243
+ this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left);
22244
+ };
22245
+
22246
+ this.$frozen = false;
22247
+ this.freeze = function() {
22248
+ this.$frozen = true;
22249
+ };
22250
+
22251
+ this.unfreeze = function() {
22252
+ this.$frozen = false;
22253
+ };
22254
+
22255
+ this.$renderChanges = function(changes, force) {
22256
+ if (this.$changes) {
22257
+ changes |= this.$changes;
22258
+ this.$changes = 0;
22259
+ }
22260
+ if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) {
22261
+ this.$changes |= changes;
22262
+ return;
22263
+ }
22264
+ if (this.$size.$dirty) {
22265
+ this.$changes |= changes;
22266
+ return this.onResize(true);
22267
+ }
22268
+ if (!this.lineHeight) {
22269
+ this.$textLayer.checkForSizeChanges();
22270
+ }
22271
+
22272
+ this._signal("beforeRender");
22273
+ var config = this.layerConfig;
22274
+ if (changes & this.CHANGE_FULL ||
22275
+ changes & this.CHANGE_SIZE ||
22276
+ changes & this.CHANGE_TEXT ||
22277
+ changes & this.CHANGE_LINES ||
22278
+ changes & this.CHANGE_SCROLL ||
22279
+ changes & this.CHANGE_H_SCROLL
22280
+ ) {
22281
+ changes |= this.$computeLayerConfig();
22282
+ if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) {
22283
+ var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight;
22284
+ if (st > 0) {
22285
+ this.scrollTop = st;
22286
+ changes = changes | this.CHANGE_SCROLL;
22287
+ changes |= this.$computeLayerConfig();
22288
+ }
22289
+ }
22290
+ config = this.layerConfig;
22291
+ this.$updateScrollBarV();
22292
+ if (changes & this.CHANGE_H_SCROLL)
22293
+ this.$updateScrollBarH();
22294
+ this.$gutterLayer.element.style.marginTop = (-config.offset) + "px";
22295
+ this.content.style.marginTop = (-config.offset) + "px";
22296
+ this.content.style.width = config.width + 2 * this.$padding + "px";
22297
+ this.content.style.height = config.minHeight + "px";
22298
+ }
22299
+ if (changes & this.CHANGE_H_SCROLL) {
22300
+ this.content.style.marginLeft = -this.scrollLeft + "px";
22301
+ this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left";
22302
+ }
22303
+ if (changes & this.CHANGE_FULL) {
22304
+ this.$textLayer.update(config);
22305
+ if (this.$showGutter)
22306
+ this.$gutterLayer.update(config);
22307
+ this.$markerBack.update(config);
22308
+ this.$markerFront.update(config);
22309
+ this.$cursorLayer.update(config);
22310
+ this.$moveTextAreaToCursor();
22311
+ this.$highlightGutterLine && this.$updateGutterLineHighlight();
22312
+ this._signal("afterRender");
22313
+ return;
22314
+ }
22315
+ if (changes & this.CHANGE_SCROLL) {
22316
+ if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
22317
+ this.$textLayer.update(config);
22318
+ else
22319
+ this.$textLayer.scrollLines(config);
22320
+
22321
+ if (this.$showGutter)
22322
+ this.$gutterLayer.update(config);
22323
+ this.$markerBack.update(config);
22324
+ this.$markerFront.update(config);
22325
+ this.$cursorLayer.update(config);
22326
+ this.$highlightGutterLine && this.$updateGutterLineHighlight();
22327
+ this.$moveTextAreaToCursor();
22328
+ this._signal("afterRender");
22329
+ return;
22330
+ }
22331
+
22332
+ if (changes & this.CHANGE_TEXT) {
22333
+ this.$textLayer.update(config);
22334
+ if (this.$showGutter)
22335
+ this.$gutterLayer.update(config);
22336
+ }
22337
+ else if (changes & this.CHANGE_LINES) {
22338
+ if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter)
22339
+ this.$gutterLayer.update(config);
22340
+ }
22341
+ else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) {
22342
+ if (this.$showGutter)
22343
+ this.$gutterLayer.update(config);
22344
+ }
22345
+
22346
+ if (changes & this.CHANGE_CURSOR) {
22347
+ this.$cursorLayer.update(config);
22348
+ this.$moveTextAreaToCursor();
22349
+ this.$highlightGutterLine && this.$updateGutterLineHighlight();
22350
+ }
22351
+
22352
+ if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
22353
+ this.$markerFront.update(config);
22354
+ }
22355
+
22356
+ if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {
22357
+ this.$markerBack.update(config);
22358
+ }
22359
+
22360
+ this._signal("afterRender");
22361
+ };
22362
+
22363
+
22364
+ this.$autosize = function() {
22365
+ var height = this.session.getScreenLength() * this.lineHeight;
22366
+ var maxHeight = this.$maxLines * this.lineHeight;
22367
+ var desiredHeight = Math.max(
22368
+ (this.$minLines||1) * this.lineHeight,
22369
+ Math.min(maxHeight, height)
22370
+ ) + this.scrollMargin.v + (this.$extraHeight || 0);
22371
+ var vScroll = height > maxHeight;
22372
+
22373
+ if (desiredHeight != this.desiredHeight ||
22374
+ this.$size.height != this.desiredHeight || vScroll != this.$vScroll) {
22375
+ if (vScroll != this.$vScroll) {
22376
+ this.$vScroll = vScroll;
22377
+ this.scrollBarV.setVisible(vScroll);
22378
+ }
22379
+
22380
+ var w = this.container.clientWidth;
22381
+ this.container.style.height = desiredHeight + "px";
22382
+ this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight);
22383
+ this.desiredHeight = desiredHeight;
22384
+
22385
+ this._signal("autosize");
22386
+ }
22387
+ };
22388
+
22389
+ this.$computeLayerConfig = function() {
22390
+ if (this.$maxLines && this.lineHeight > 1)
22391
+ this.$autosize();
22392
+
22393
+ var session = this.session;
22394
+ var size = this.$size;
22395
+
22396
+ var hideScrollbars = size.height <= 2 * this.lineHeight;
22397
+ var screenLines = this.session.getScreenLength();
22398
+ var maxHeight = screenLines * this.lineHeight;
22399
+
22400
+ var offset = this.scrollTop % this.lineHeight;
22401
+ var minHeight = size.scrollerHeight + this.lineHeight;
22402
+
22403
+ var longestLine = this.$getLongestLine();
22404
+
22405
+ var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||
22406
+ size.scrollerWidth - longestLine - 2 * this.$padding < 0);
22407
+
22408
+ var hScrollChanged = this.$horizScroll !== horizScroll;
22409
+ if (hScrollChanged) {
22410
+ this.$horizScroll = horizScroll;
22411
+ this.scrollBarH.setVisible(horizScroll);
22412
+ }
22413
+
22414
+ var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd
22415
+ ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
22416
+ : 0;
22417
+ maxHeight += scrollPastEnd;
22418
+
22419
+ this.session.setScrollTop(Math.max(-this.scrollMargin.top,
22420
+ Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom)));
22421
+
22422
+ this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft,
22423
+ longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right)));
22424
+
22425
+ var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
22426
+ size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop);
22427
+ var vScrollChanged = this.$vScroll !== vScroll;
22428
+ if (vScrollChanged) {
22429
+ this.$vScroll = vScroll;
22430
+ this.scrollBarV.setVisible(vScroll);
22431
+ }
22432
+
22433
+ var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
22434
+ var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
22435
+ var lastRow = firstRow + lineCount;
22436
+ var firstRowScreen, firstRowHeight;
22437
+ var lineHeight = this.lineHeight;
22438
+ firstRow = session.screenToDocumentRow(firstRow, 0);
22439
+ var foldLine = session.getFoldLine(firstRow);
22440
+ if (foldLine) {
22441
+ firstRow = foldLine.start.row;
22442
+ }
22443
+
22444
+ firstRowScreen = session.documentToScreenRow(firstRow, 0);
22445
+ firstRowHeight = session.getRowLength(firstRow) * lineHeight;
22446
+
22447
+ lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);
22448
+ minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight +
22449
+ firstRowHeight;
22450
+
22451
+ offset = this.scrollTop - firstRowScreen * lineHeight;
22452
+
22453
+ var changes = 0;
22454
+ if (this.layerConfig.width != longestLine)
22455
+ changes = this.CHANGE_H_SCROLL;
22456
+ if (hScrollChanged || vScrollChanged) {
22457
+ changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height);
22458
+ this._signal("scrollbarVisibilityChanged");
22459
+ if (vScrollChanged)
22460
+ longestLine = this.$getLongestLine();
22461
+ }
22462
+
22463
+ this.layerConfig = {
22464
+ width : longestLine,
22465
+ padding : this.$padding,
22466
+ firstRow : firstRow,
22467
+ firstRowScreen: firstRowScreen,
22468
+ lastRow : lastRow,
22469
+ lineHeight : lineHeight,
22470
+ characterWidth : this.characterWidth,
22471
+ minHeight : minHeight,
22472
+ maxHeight : maxHeight,
22473
+ offset : offset,
22474
+ gutterOffset : Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)),
22475
+ height : this.$size.scrollerHeight
22476
+ };
22477
+
22478
+ return changes;
22479
+ };
22480
+
22481
+ this.$updateLines = function() {
22482
+ var firstRow = this.$changedLines.firstRow;
22483
+ var lastRow = this.$changedLines.lastRow;
22484
+ this.$changedLines = null;
22485
+
22486
+ var layerConfig = this.layerConfig;
22487
+
22488
+ if (firstRow > layerConfig.lastRow + 1) { return; }
22489
+ if (lastRow < layerConfig.firstRow) { return; }
22490
+ if (lastRow === Infinity) {
22491
+ if (this.$showGutter)
22492
+ this.$gutterLayer.update(layerConfig);
22493
+ this.$textLayer.update(layerConfig);
22494
+ return;
22495
+ }
22496
+ this.$textLayer.updateLines(layerConfig, firstRow, lastRow);
22497
+ return true;
22498
+ };
22499
+
22500
+ this.$getLongestLine = function() {
22501
+ var charCount = this.session.getScreenWidth();
22502
+ if (this.showInvisibles && !this.session.$useWrapMode)
22503
+ charCount += 1;
22504
+
22505
+ return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth));
22506
+ };
22507
+ this.updateFrontMarkers = function() {
22508
+ this.$markerFront.setMarkers(this.session.getMarkers(true));
22509
+ this.$loop.schedule(this.CHANGE_MARKER_FRONT);
22510
+ };
22511
+ this.updateBackMarkers = function() {
22512
+ this.$markerBack.setMarkers(this.session.getMarkers());
22513
+ this.$loop.schedule(this.CHANGE_MARKER_BACK);
22514
+ };
22515
+ this.addGutterDecoration = function(row, className){
22516
+ this.$gutterLayer.addGutterDecoration(row, className);
22517
+ };
22518
+ this.removeGutterDecoration = function(row, className){
22519
+ this.$gutterLayer.removeGutterDecoration(row, className);
22520
+ };
22521
+ this.updateBreakpoints = function(rows) {
22522
+ this.$loop.schedule(this.CHANGE_GUTTER);
22523
+ };
22524
+ this.setAnnotations = function(annotations) {
22525
+ this.$gutterLayer.setAnnotations(annotations);
22526
+ this.$loop.schedule(this.CHANGE_GUTTER);
22527
+ };
22528
+ this.updateCursor = function() {
22529
+ this.$loop.schedule(this.CHANGE_CURSOR);
22530
+ };
22531
+ this.hideCursor = function() {
22532
+ this.$cursorLayer.hideCursor();
22533
+ };
22534
+ this.showCursor = function() {
22535
+ this.$cursorLayer.showCursor();
22536
+ };
22537
+
22538
+ this.scrollSelectionIntoView = function(anchor, lead, offset) {
22539
+ this.scrollCursorIntoView(anchor, offset);
22540
+ this.scrollCursorIntoView(lead, offset);
22541
+ };
22542
+ this.scrollCursorIntoView = function(cursor, offset, $viewMargin) {
22543
+ if (this.$size.scrollerHeight === 0)
22544
+ return;
22545
+
22546
+ var pos = this.$cursorLayer.getPixelPosition(cursor);
22547
+
22548
+ var left = pos.left;
22549
+ var top = pos.top;
22550
+
22551
+ var topMargin = $viewMargin && $viewMargin.top || 0;
22552
+ var bottomMargin = $viewMargin && $viewMargin.bottom || 0;
22553
+
22554
+ var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop;
22555
+
22556
+ if (scrollTop + topMargin > top) {
22557
+ if (offset)
22558
+ top -= offset * this.$size.scrollerHeight;
22559
+ if (top === 0)
22560
+ top = -this.scrollMargin.top;
22561
+ this.session.setScrollTop(top);
22562
+ } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) {
22563
+ if (offset)
22564
+ top += offset * this.$size.scrollerHeight;
22565
+ this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight);
22566
+ }
22567
+
22568
+ var scrollLeft = this.scrollLeft;
22569
+
22570
+ if (scrollLeft > left) {
22571
+ if (left < this.$padding + 2 * this.layerConfig.characterWidth)
22572
+ left = -this.scrollMargin.left;
22573
+ this.session.setScrollLeft(left);
22574
+ } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
22575
+ this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
22576
+ } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) {
22577
+ this.session.setScrollLeft(0);
22578
+ }
22579
+ };
22580
+ this.getScrollTop = function() {
22581
+ return this.session.getScrollTop();
22582
+ };
22583
+ this.getScrollLeft = function() {
22584
+ return this.session.getScrollLeft();
22585
+ };
22586
+ this.getScrollTopRow = function() {
22587
+ return this.scrollTop / this.lineHeight;
22588
+ };
22589
+ this.getScrollBottomRow = function() {
22590
+ return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);
22591
+ };
22592
+ this.scrollToRow = function(row) {
22593
+ this.session.setScrollTop(row * this.lineHeight);
22594
+ };
22595
+
22596
+ this.alignCursor = function(cursor, alignment) {
22597
+ if (typeof cursor == "number")
22598
+ cursor = {row: cursor, column: 0};
22599
+
22600
+ var pos = this.$cursorLayer.getPixelPosition(cursor);
22601
+ var h = this.$size.scrollerHeight - this.lineHeight;
22602
+ var offset = pos.top - h * (alignment || 0);
22603
+
22604
+ this.session.setScrollTop(offset);
22605
+ return offset;
22606
+ };
22607
+
22608
+ this.STEPS = 8;
22609
+ this.$calcSteps = function(fromValue, toValue){
22610
+ var i = 0;
22611
+ var l = this.STEPS;
22612
+ var steps = [];
22613
+
22614
+ var func = function(t, x_min, dx) {
22615
+ return dx * (Math.pow(t - 1, 3) + 1) + x_min;
22616
+ };
22617
+
22618
+ for (i = 0; i < l; ++i)
22619
+ steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));
22620
+
22621
+ return steps;
22622
+ };
22623
+ this.scrollToLine = function(line, center, animate, callback) {
22624
+ var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});
22625
+ var offset = pos.top;
22626
+ if (center)
22627
+ offset -= this.$size.scrollerHeight / 2;
22628
+
22629
+ var initialScroll = this.scrollTop;
22630
+ this.session.setScrollTop(offset);
22631
+ if (animate !== false)
22632
+ this.animateScrolling(initialScroll, callback);
22633
+ };
22634
+
22635
+ this.animateScrolling = function(fromValue, callback) {
22636
+ var toValue = this.scrollTop;
22637
+ if (!this.$animatedScroll)
22638
+ return;
22639
+ var _self = this;
22640
+
22641
+ if (fromValue == toValue)
22642
+ return;
22643
+
22644
+ if (this.$scrollAnimation) {
22645
+ var oldSteps = this.$scrollAnimation.steps;
22646
+ if (oldSteps.length) {
22647
+ fromValue = oldSteps[0];
22648
+ if (fromValue == toValue)
22649
+ return;
22650
+ }
22651
+ }
22652
+
22653
+ var steps = _self.$calcSteps(fromValue, toValue);
22654
+ this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps};
22655
+
22656
+ clearInterval(this.$timer);
22657
+
22658
+ _self.session.setScrollTop(steps.shift());
22659
+ _self.session.$scrollTop = toValue;
22660
+ this.$timer = setInterval(function() {
22661
+ if (steps.length) {
22662
+ _self.session.setScrollTop(steps.shift());
22663
+ _self.session.$scrollTop = toValue;
22664
+ } else if (toValue != null) {
22665
+ _self.session.$scrollTop = -1;
22666
+ _self.session.setScrollTop(toValue);
22667
+ toValue = null;
22668
+ } else {
22669
+ _self.$timer = clearInterval(_self.$timer);
22670
+ _self.$scrollAnimation = null;
22671
+ callback && callback();
22672
+ }
22673
+ }, 10);
22674
+ };
22675
+ this.scrollToY = function(scrollTop) {
22676
+ if (this.scrollTop !== scrollTop) {
22677
+ this.$loop.schedule(this.CHANGE_SCROLL);
22678
+ this.scrollTop = scrollTop;
22679
+ }
22680
+ };
22681
+ this.scrollToX = function(scrollLeft) {
22682
+ if (this.scrollLeft !== scrollLeft)
22683
+ this.scrollLeft = scrollLeft;
22684
+ this.$loop.schedule(this.CHANGE_H_SCROLL);
22685
+ };
22686
+ this.scrollTo = function(x, y) {
22687
+ this.session.setScrollTop(y);
22688
+ this.session.setScrollLeft(y);
22689
+ };
22690
+ this.scrollBy = function(deltaX, deltaY) {
22691
+ deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY);
22692
+ deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);
22693
+ };
22694
+ this.isScrollableBy = function(deltaX, deltaY) {
22695
+ if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top)
22696
+ return true;
22697
+ if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight
22698
+ - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom)
22699
+ return true;
22700
+ if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left)
22701
+ return true;
22702
+ if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth
22703
+ - this.layerConfig.width < -1 + this.scrollMargin.right)
22704
+ return true;
22705
+ };
22706
+
22707
+ this.pixelToScreenCoordinates = function(x, y) {
22708
+ var canvasPos = this.scroller.getBoundingClientRect();
22709
+
22710
+ var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth;
22711
+ var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight);
22712
+ var col = Math.round(offset);
22713
+
22714
+ return {row: row, column: col, side: offset - col > 0 ? 1 : -1};
22715
+ };
22716
+
22717
+ this.screenToTextCoordinates = function(x, y) {
22718
+ var canvasPos = this.scroller.getBoundingClientRect();
22719
+
22720
+ var col = Math.round(
22721
+ (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth
22722
+ );
22723
+
22724
+ var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight;
22725
+
22726
+ return this.session.screenToDocumentPosition(row, Math.max(col, 0));
22727
+ };
22728
+ this.textToScreenCoordinates = function(row, column) {
22729
+ var canvasPos = this.scroller.getBoundingClientRect();
22730
+ var pos = this.session.documentToScreenPosition(row, column);
22731
+
22732
+ var x = this.$padding + Math.round(pos.column * this.characterWidth);
22733
+ var y = pos.row * this.lineHeight;
22734
+
22735
+ return {
22736
+ pageX: canvasPos.left + x - this.scrollLeft,
22737
+ pageY: canvasPos.top + y - this.scrollTop
22738
+ };
22739
+ };
22740
+ this.visualizeFocus = function() {
22741
+ dom.addCssClass(this.container, "ace_focus");
22742
+ };
22743
+ this.visualizeBlur = function() {
22744
+ dom.removeCssClass(this.container, "ace_focus");
22745
+ };
22746
+ this.showComposition = function(position) {
22747
+ if (!this.$composition)
22748
+ this.$composition = {
22749
+ keepTextAreaAtCursor: this.$keepTextAreaAtCursor,
22750
+ cssText: this.textarea.style.cssText
22751
+ };
22752
+
22753
+ this.$keepTextAreaAtCursor = true;
22754
+ dom.addCssClass(this.textarea, "ace_composition");
22755
+ this.textarea.style.cssText = "";
22756
+ this.$moveTextAreaToCursor();
22757
+ };
22758
+ this.setCompositionText = function(text) {
22759
+ this.$moveTextAreaToCursor();
22760
+ };
22761
+ this.hideComposition = function() {
22762
+ if (!this.$composition)
22763
+ return;
22764
+
22765
+ dom.removeCssClass(this.textarea, "ace_composition");
22766
+ this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor;
22767
+ this.textarea.style.cssText = this.$composition.cssText;
22768
+ this.$composition = null;
22769
+ };
22770
+ this.setTheme = function(theme, cb) {
22771
+ var _self = this;
22772
+ this.$themeId = theme;
22773
+ _self._dispatchEvent('themeChange',{theme:theme});
22774
+
22775
+ if (!theme || typeof theme == "string") {
22776
+ var moduleName = theme || this.$options.theme.initialValue;
22777
+ config.loadModule(["theme", moduleName], afterLoad);
22778
+ } else {
22779
+ afterLoad(theme);
22780
+ }
22781
+
22782
+ function afterLoad(module) {
22783
+ if (_self.$themeId != theme)
22784
+ return cb && cb();
22785
+ if (!module.cssClass)
22786
+ return;
22787
+ dom.importCssString(
22788
+ module.cssText,
22789
+ module.cssClass,
22790
+ _self.container.ownerDocument
22791
+ );
22792
+
22793
+ if (_self.theme)
22794
+ dom.removeCssClass(_self.container, _self.theme.cssClass);
22795
+
22796
+ var padding = "padding" in module ? module.padding
22797
+ : "padding" in (_self.theme || {}) ? 4 : _self.$padding;
22798
+ if (_self.$padding && padding != _self.$padding)
22799
+ _self.setPadding(padding);
22800
+ _self.$theme = module.cssClass;
22801
+
22802
+ _self.theme = module;
22803
+ dom.addCssClass(_self.container, module.cssClass);
22804
+ dom.setCssClass(_self.container, "ace_dark", module.isDark);
22805
+ if (_self.$size) {
22806
+ _self.$size.width = 0;
22807
+ _self.$updateSizeAsync();
22808
+ }
22809
+
22810
+ _self._dispatchEvent('themeLoaded', {theme:module});
22811
+ cb && cb();
22812
+ }
22813
+ };
22814
+ this.getTheme = function() {
22815
+ return this.$themeId;
22816
+ };
22817
+ this.setStyle = function(style, include) {
22818
+ dom.setCssClass(this.container, style, include !== false);
22819
+ };
22820
+ this.unsetStyle = function(style) {
22821
+ dom.removeCssClass(this.container, style);
22822
+ };
22823
+
22824
+ this.setCursorStyle = function(style) {
22825
+ if (this.scroller.style.cursor != style)
22826
+ this.scroller.style.cursor = style;
22827
+ };
22828
+ this.setMouseCursor = function(cursorStyle) {
22829
+ this.scroller.style.cursor = cursorStyle;
22830
+ };
22831
+ this.destroy = function() {
22832
+ this.$textLayer.destroy();
22833
+ this.$cursorLayer.destroy();
22834
+ };
22835
+
22836
+ }).call(VirtualRenderer.prototype);
22837
+
22838
+
22839
+ config.defineOptions(VirtualRenderer.prototype, "renderer", {
22840
+ animatedScroll: {initialValue: false},
22841
+ showInvisibles: {
22842
+ set: function(value) {
22843
+ if (this.$textLayer.setShowInvisibles(value))
22844
+ this.$loop.schedule(this.CHANGE_TEXT);
22845
+ },
22846
+ initialValue: false
22847
+ },
22848
+ showPrintMargin: {
22849
+ set: function() { this.$updatePrintMargin(); },
22850
+ initialValue: true
22851
+ },
22852
+ printMarginColumn: {
22853
+ set: function() { this.$updatePrintMargin(); },
22854
+ initialValue: 80
22855
+ },
22856
+ printMargin: {
22857
+ set: function(val) {
22858
+ if (typeof val == "number")
22859
+ this.$printMarginColumn = val;
22860
+ this.$showPrintMargin = !!val;
22861
+ this.$updatePrintMargin();
22862
+ },
22863
+ get: function() {
22864
+ return this.$showPrintMargin && this.$printMarginColumn;
22865
+ }
22866
+ },
22867
+ showGutter: {
22868
+ set: function(show){
22869
+ this.$gutter.style.display = show ? "block" : "none";
22870
+ this.$loop.schedule(this.CHANGE_FULL);
22871
+ this.onGutterResize();
22872
+ },
22873
+ initialValue: true
22874
+ },
22875
+ fadeFoldWidgets: {
22876
+ set: function(show) {
22877
+ dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show);
22878
+ },
22879
+ initialValue: false
22880
+ },
22881
+ showFoldWidgets: {
22882
+ set: function(show) {this.$gutterLayer.setShowFoldWidgets(show)},
22883
+ initialValue: true
22884
+ },
22885
+ showLineNumbers: {
22886
+ set: function(show) {
22887
+ this.$gutterLayer.setShowLineNumbers(show);
22888
+ this.$loop.schedule(this.CHANGE_GUTTER);
22889
+ },
22890
+ initialValue: true
22891
+ },
22892
+ displayIndentGuides: {
22893
+ set: function(show) {
22894
+ if (this.$textLayer.setDisplayIndentGuides(show))
22895
+ this.$loop.schedule(this.CHANGE_TEXT);
22896
+ },
22897
+ initialValue: true
22898
+ },
22899
+ highlightGutterLine: {
22900
+ set: function(shouldHighlight) {
22901
+ if (!this.$gutterLineHighlight) {
22902
+ this.$gutterLineHighlight = dom.createElement("div");
22903
+ this.$gutterLineHighlight.className = "ace_gutter-active-line";
22904
+ this.$gutter.appendChild(this.$gutterLineHighlight);
22905
+ return;
22906
+ }
22907
+
22908
+ this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none";
22909
+ if (this.$cursorLayer.$pixelPos)
22910
+ this.$updateGutterLineHighlight();
22911
+ },
22912
+ initialValue: false,
22913
+ value: true
22914
+ },
22915
+ hScrollBarAlwaysVisible: {
22916
+ set: function(val) {
22917
+ if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll)
22918
+ this.$loop.schedule(this.CHANGE_SCROLL);
22919
+ },
22920
+ initialValue: false
22921
+ },
22922
+ vScrollBarAlwaysVisible: {
22923
+ set: function(val) {
22924
+ if (!this.$vScrollBarAlwaysVisible || !this.$vScroll)
22925
+ this.$loop.schedule(this.CHANGE_SCROLL);
22926
+ },
22927
+ initialValue: false
22928
+ },
22929
+ fontSize: {
22930
+ set: function(size) {
22931
+ if (typeof size == "number")
22932
+ size = size + "px";
22933
+ this.container.style.fontSize = size;
22934
+ this.updateFontSize();
22935
+ },
22936
+ initialValue: 12
22937
+ },
22938
+ fontFamily: {
22939
+ set: function(name) {
22940
+ this.container.style.fontFamily = name;
22941
+ this.updateFontSize();
22942
+ }
22943
+ },
22944
+ maxLines: {
22945
+ set: function(val) {
22946
+ this.updateFull();
22947
+ }
22948
+ },
22949
+ minLines: {
22950
+ set: function(val) {
22951
+ this.updateFull();
22952
+ }
22953
+ },
22954
+ scrollPastEnd: {
22955
+ set: function(val) {
22956
+ val = +val || 0;
22957
+ if (this.$scrollPastEnd == val)
22958
+ return;
22959
+ this.$scrollPastEnd = val;
22960
+ this.$loop.schedule(this.CHANGE_SCROLL);
22961
+ },
22962
+ initialValue: 0,
22963
+ handlesSet: true
22964
+ },
22965
+ fixedWidthGutter: {
22966
+ set: function(val) {
22967
+ this.$gutterLayer.$fixedWidth = !!val;
22968
+ this.$loop.schedule(this.CHANGE_GUTTER);
22969
+ }
22970
+ },
22971
+ theme: {
22972
+ set: function(val) { this.setTheme(val) },
22973
+ get: function() { return this.$themeId || this.theme; },
22974
+ initialValue: "./theme/textmate",
22975
+ handlesSet: true
22976
+ }
22977
+ });
22978
+
22979
+ exports.VirtualRenderer = VirtualRenderer;
22980
+ });
22981
+
22982
+ ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(acequire, exports, module) {
22983
+ "use strict";
22984
+
22985
+ var oop = acequire("../lib/oop");
22986
+ var net = acequire("../lib/net");
22987
+ var EventEmitter = acequire("../lib/event_emitter").EventEmitter;
22988
+ var config = acequire("../config");
22989
+
22990
+ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
22991
+ this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
22992
+ this.changeListener = this.changeListener.bind(this);
22993
+ this.onMessage = this.onMessage.bind(this);
22994
+ if (acequire.nameToUrl && !acequire.toUrl)
22995
+ acequire.toUrl = acequire.nameToUrl;
22996
+
22997
+ if (config.get("packaged") || !acequire.toUrl) {
22998
+ workerUrl = workerUrl || config.moduleUrl(mod.id, "worker")
22999
+ } else {
23000
+ var normalizePath = this.$normalizePath;
23001
+ workerUrl = workerUrl || normalizePath(acequire.toUrl("ace/worker/worker.js", null, "_"));
23002
+
23003
+ var tlns = {};
23004
+ topLevelNamespaces.forEach(function(ns) {
23005
+ tlns[ns] = normalizePath(acequire.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, ""));
23006
+ });
23007
+ }
23008
+
23009
+ try {
23010
+ var workerSrc = mod.src;
23011
+ var Blob = __webpack_require__(19);
23012
+ var blob = new Blob([ workerSrc ], { type: 'application/javascript' });
23013
+ var blobUrl = (window.URL || window.webkitURL).createObjectURL(blob);
23014
+
23015
+ this.$worker = new Worker(blobUrl);
23016
+
23017
+ } catch(e) {
23018
+ if (e instanceof window.DOMException) {
23019
+ var blob = this.$workerBlob(workerUrl);
23020
+ var URL = window.URL || window.webkitURL;
23021
+ var blobURL = URL.createObjectURL(blob);
23022
+
23023
+ this.$worker = new Worker(blobURL);
23024
+ URL.revokeObjectURL(blobURL);
23025
+ } else {
23026
+ throw e;
23027
+ }
23028
+ }
23029
+ this.$worker.postMessage({
23030
+ init : true,
23031
+ tlns : tlns,
23032
+ module : mod.id,
23033
+ classname : classname
23034
+ });
23035
+
23036
+ this.callbackId = 1;
23037
+ this.callbacks = {};
23038
+
23039
+ this.$worker.onmessage = this.onMessage;
23040
+ };
23041
+
23042
+ (function(){
23043
+
23044
+ oop.implement(this, EventEmitter);
23045
+
23046
+ this.onMessage = function(e) {
23047
+ var msg = e.data;
23048
+ switch(msg.type) {
23049
+ case "event":
23050
+ this._signal(msg.name, {data: msg.data});
23051
+ break;
23052
+ case "call":
23053
+ var callback = this.callbacks[msg.id];
23054
+ if (callback) {
23055
+ callback(msg.data);
23056
+ delete this.callbacks[msg.id];
23057
+ }
23058
+ break;
23059
+ case "error":
23060
+ this.reportError(msg.data);
23061
+ break;
23062
+ case "log":
23063
+ window.console && console.log && console.log.apply(console, msg.data);
23064
+ break;
23065
+ }
23066
+ };
23067
+
23068
+ this.reportError = function(err) {
23069
+ window.console && console.error && console.error(err);
23070
+ };
23071
+
23072
+ this.$normalizePath = function(path) {
23073
+ return net.qualifyURL(path);
23074
+ };
23075
+
23076
+ this.terminate = function() {
23077
+ this._signal("terminate", {});
23078
+ this.deltaQueue = null;
23079
+ this.$worker.terminate();
23080
+ this.$worker = null;
23081
+ if (this.$doc)
23082
+ this.$doc.off("change", this.changeListener);
23083
+ this.$doc = null;
23084
+ };
23085
+
23086
+ this.send = function(cmd, args) {
23087
+ this.$worker.postMessage({command: cmd, args: args});
23088
+ };
23089
+
23090
+ this.call = function(cmd, args, callback) {
23091
+ if (callback) {
23092
+ var id = this.callbackId++;
23093
+ this.callbacks[id] = callback;
23094
+ args.push(id);
23095
+ }
23096
+ this.send(cmd, args);
23097
+ };
23098
+
23099
+ this.emit = function(event, data) {
23100
+ try {
23101
+ this.$worker.postMessage({event: event, data: {data: data.data}});
23102
+ }
23103
+ catch(ex) {
23104
+ console.error(ex.stack);
23105
+ }
23106
+ };
23107
+
23108
+ this.attachToDocument = function(doc) {
23109
+ if(this.$doc)
23110
+ this.terminate();
23111
+
23112
+ this.$doc = doc;
23113
+ this.call("setValue", [doc.getValue()]);
23114
+ doc.on("change", this.changeListener);
23115
+ };
23116
+
23117
+ this.changeListener = function(e) {
23118
+ if (!this.deltaQueue) {
23119
+ this.deltaQueue = [e.data];
23120
+ setTimeout(this.$sendDeltaQueue, 0);
23121
+ } else
23122
+ this.deltaQueue.push(e.data);
23123
+ };
23124
+
23125
+ this.$sendDeltaQueue = function() {
23126
+ var q = this.deltaQueue;
23127
+ if (!q) return;
23128
+ this.deltaQueue = null;
23129
+ if (q.length > 20 && q.length > this.$doc.getLength() >> 1) {
23130
+ this.call("setValue", [this.$doc.getValue()]);
23131
+ } else
23132
+ this.emit("change", {data: q});
23133
+ };
23134
+
23135
+ this.$workerBlob = function(workerUrl) {
23136
+ var script = "importScripts('" + net.qualifyURL(workerUrl) + "');";
23137
+ try {
23138
+ return new Blob([script], {"type": "application/javascript"});
23139
+ } catch (e) { // Backwards-compatibility
23140
+ var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
23141
+ var blobBuilder = new BlobBuilder();
23142
+ blobBuilder.append(script);
23143
+ return blobBuilder.getBlob("application/javascript");
23144
+ }
23145
+ };
23146
+
23147
+ }).call(WorkerClient.prototype);
23148
+
23149
+
23150
+ var UIWorkerClient = function(topLevelNamespaces, mod, classname) {
23151
+ this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
23152
+ this.changeListener = this.changeListener.bind(this);
23153
+ this.callbackId = 1;
23154
+ this.callbacks = {};
23155
+ this.messageBuffer = [];
23156
+
23157
+ var main = null;
23158
+ var emitSync = false;
23159
+ var sender = Object.create(EventEmitter);
23160
+ var _self = this;
23161
+
23162
+ this.$worker = {};
23163
+ this.$worker.terminate = function() {};
23164
+ this.$worker.postMessage = function(e) {
23165
+ _self.messageBuffer.push(e);
23166
+ if (main) {
23167
+ if (emitSync)
23168
+ setTimeout(processNext);
23169
+ else
23170
+ processNext();
23171
+ }
23172
+ };
23173
+ this.setEmitSync = function(val) { emitSync = val };
23174
+
23175
+ var processNext = function() {
23176
+ var msg = _self.messageBuffer.shift();
23177
+ if (msg.command)
23178
+ main[msg.command].apply(main, msg.args);
23179
+ else if (msg.event)
23180
+ sender._signal(msg.event, msg.data);
23181
+ };
23182
+
23183
+ sender.postMessage = function(msg) {
23184
+ _self.onMessage({data: msg});
23185
+ };
23186
+ sender.callback = function(data, callbackId) {
23187
+ this.postMessage({type: "call", id: callbackId, data: data});
23188
+ };
23189
+ sender.emit = function(name, data) {
23190
+ this.postMessage({type: "event", name: name, data: data});
23191
+ };
23192
+
23193
+ config.loadModule(["worker", mod], function(Main) {
23194
+ main = new Main[classname](sender);
23195
+ while (_self.messageBuffer.length)
23196
+ processNext();
23197
+ });
23198
+ };
23199
+
23200
+ UIWorkerClient.prototype = WorkerClient.prototype;
23201
+
23202
+ exports.UIWorkerClient = UIWorkerClient;
23203
+ exports.WorkerClient = WorkerClient;
23204
+
23205
+ });
23206
+
23207
+ ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(acequire, exports, module) {
23208
+ "use strict";
23209
+
23210
+ var Range = acequire("./range").Range;
23211
+ var EventEmitter = acequire("./lib/event_emitter").EventEmitter;
23212
+ var oop = acequire("./lib/oop");
23213
+
23214
+ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {
23215
+ var _self = this;
23216
+ this.length = length;
23217
+ this.session = session;
23218
+ this.doc = session.getDocument();
23219
+ this.mainClass = mainClass;
23220
+ this.othersClass = othersClass;
23221
+ this.$onUpdate = this.onUpdate.bind(this);
23222
+ this.doc.on("change", this.$onUpdate);
23223
+ this.$others = others;
23224
+
23225
+ this.$onCursorChange = function() {
23226
+ setTimeout(function() {
23227
+ _self.onCursorChange();
23228
+ });
23229
+ };
23230
+
23231
+ this.$pos = pos;
23232
+ var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
23233
+ this.$undoStackDepth = undoStack.length;
23234
+ this.setup();
23235
+
23236
+ session.selection.on("changeCursor", this.$onCursorChange);
23237
+ };
23238
+
23239
+ (function() {
23240
+
23241
+ oop.implement(this, EventEmitter);
23242
+ this.setup = function() {
23243
+ var _self = this;
23244
+ var doc = this.doc;
23245
+ var session = this.session;
23246
+ var pos = this.$pos;
23247
+
23248
+ this.selectionBefore = session.selection.toJSON();
23249
+ if (session.selection.inMultiSelectMode)
23250
+ session.selection.toSingleRange();
23251
+
23252
+ this.pos = doc.createAnchor(pos.row, pos.column);
23253
+ this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
23254
+ this.pos.on("change", function(event) {
23255
+ session.removeMarker(_self.markerId);
23256
+ _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false);
23257
+ });
23258
+ this.others = [];
23259
+ this.$others.forEach(function(other) {
23260
+ var anchor = doc.createAnchor(other.row, other.column);
23261
+ _self.others.push(anchor);
23262
+ });
23263
+ session.setUndoSelect(false);
23264
+ };
23265
+ this.showOtherMarkers = function() {
23266
+ if(this.othersActive) return;
23267
+ var session = this.session;
23268
+ var _self = this;
23269
+ this.othersActive = true;
23270
+ this.others.forEach(function(anchor) {
23271
+ anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);
23272
+ anchor.on("change", function(event) {
23273
+ session.removeMarker(anchor.markerId);
23274
+ anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false);
23275
+ });
23276
+ });
23277
+ };
23278
+ this.hideOtherMarkers = function() {
23279
+ if(!this.othersActive) return;
23280
+ this.othersActive = false;
23281
+ for (var i = 0; i < this.others.length; i++) {
23282
+ this.session.removeMarker(this.others[i].markerId);
23283
+ }
23284
+ };
23285
+ this.onUpdate = function(event) {
23286
+ var delta = event.data;
23287
+ var range = delta.range;
23288
+ if(range.start.row !== range.end.row) return;
23289
+ if(range.start.row !== this.pos.row) return;
23290
+ if (this.$updating) return;
23291
+ this.$updating = true;
23292
+ var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column;
23293
+
23294
+ if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {
23295
+ var distanceFromStart = range.start.column - this.pos.column;
23296
+ this.length += lengthDiff;
23297
+ if(!this.session.$fromUndo) {
23298
+ if(delta.action === "insertText") {
23299
+ for (var i = this.others.length - 1; i >= 0; i--) {
23300
+ var otherPos = this.others[i];
23301
+ var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
23302
+ if(otherPos.row === range.start.row && range.start.column < otherPos.column)
23303
+ newPos.column += lengthDiff;
23304
+ this.doc.insert(newPos, delta.text);
23305
+ }
23306
+ } else if(delta.action === "removeText") {
23307
+ for (var i = this.others.length - 1; i >= 0; i--) {
23308
+ var otherPos = this.others[i];
23309
+ var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
23310
+ if(otherPos.row === range.start.row && range.start.column < otherPos.column)
23311
+ newPos.column += lengthDiff;
23312
+ this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
23313
+ }
23314
+ }
23315
+ if(range.start.column === this.pos.column && delta.action === "insertText") {
23316
+ setTimeout(function() {
23317
+ this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);
23318
+ for (var i = 0; i < this.others.length; i++) {
23319
+ var other = this.others[i];
23320
+ var newPos = {row: other.row, column: other.column - lengthDiff};
23321
+ if(other.row === range.start.row && range.start.column < other.column)
23322
+ newPos.column += lengthDiff;
23323
+ other.setPosition(newPos.row, newPos.column);
23324
+ }
23325
+ }.bind(this), 0);
23326
+ }
23327
+ else if(range.start.column === this.pos.column && delta.action === "removeText") {
23328
+ setTimeout(function() {
23329
+ for (var i = 0; i < this.others.length; i++) {
23330
+ var other = this.others[i];
23331
+ if(other.row === range.start.row && range.start.column < other.column) {
23332
+ other.setPosition(other.row, other.column - lengthDiff);
23333
+ }
23334
+ }
23335
+ }.bind(this), 0);
23336
+ }
23337
+ }
23338
+ this.pos._emit("change", {value: this.pos});
23339
+ for (var i = 0; i < this.others.length; i++) {
23340
+ this.others[i]._emit("change", {value: this.others[i]});
23341
+ }
23342
+ }
23343
+ this.$updating = false;
23344
+ };
23345
+
23346
+ this.onCursorChange = function(event) {
23347
+ if (this.$updating || !this.session) return;
23348
+ var pos = this.session.selection.getCursor();
23349
+ if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) {
23350
+ this.showOtherMarkers();
23351
+ this._emit("cursorEnter", event);
23352
+ } else {
23353
+ this.hideOtherMarkers();
23354
+ this._emit("cursorLeave", event);
23355
+ }
23356
+ };
23357
+ this.detach = function() {
23358
+ this.session.removeMarker(this.markerId);
23359
+ this.hideOtherMarkers();
23360
+ this.doc.removeEventListener("change", this.$onUpdate);
23361
+ this.session.selection.removeEventListener("changeCursor", this.$onCursorChange);
23362
+ this.pos.detach();
23363
+ for (var i = 0; i < this.others.length; i++) {
23364
+ this.others[i].detach();
23365
+ }
23366
+ this.session.setUndoSelect(true);
23367
+ this.session = null;
23368
+ };
23369
+ this.cancel = function() {
23370
+ if(this.$undoStackDepth === -1)
23371
+ throw Error("Canceling placeholders only supported with undo manager attached to session.");
23372
+ var undoManager = this.session.getUndoManager();
23373
+ var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;
23374
+ for (var i = 0; i < undosRequired; i++) {
23375
+ undoManager.undo(true);
23376
+ }
23377
+ if (this.selectionBefore)
23378
+ this.session.selection.fromJSON(this.selectionBefore);
23379
+ };
23380
+ }).call(PlaceHolder.prototype);
23381
+
23382
+
23383
+ exports.PlaceHolder = PlaceHolder;
23384
+ });
23385
+
23386
+ ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) {
23387
+
23388
+ var event = acequire("../lib/event");
23389
+ var useragent = acequire("../lib/useragent");
23390
+ function isSamePoint(p1, p2) {
23391
+ return p1.row == p2.row && p1.column == p2.column;
23392
+ }
23393
+
23394
+ function onMouseDown(e) {
23395
+ var ev = e.domEvent;
23396
+ var alt = ev.altKey;
23397
+ var shift = ev.shiftKey;
23398
+ var ctrl = ev.ctrlKey;
23399
+ var accel = e.getAccelKey();
23400
+ var button = e.getButton();
23401
+
23402
+ if (ctrl && useragent.isMac)
23403
+ button = ev.button;
23404
+
23405
+ if (e.editor.inMultiSelectMode && button == 2) {
23406
+ e.editor.textInput.onContextMenu(e.domEvent);
23407
+ return;
23408
+ }
23409
+
23410
+ if (!ctrl && !alt && !accel) {
23411
+ if (button === 0 && e.editor.inMultiSelectMode)
23412
+ e.editor.exitMultiSelectMode();
23413
+ return;
23414
+ }
23415
+
23416
+ if (button !== 0)
23417
+ return;
23418
+
23419
+ var editor = e.editor;
23420
+ var selection = editor.selection;
23421
+ var isMultiSelect = editor.inMultiSelectMode;
23422
+ var pos = e.getDocumentPosition();
23423
+ var cursor = selection.getCursor();
23424
+ var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
23425
+
23426
+ var mouseX = e.x, mouseY = e.y;
23427
+ var onMouseSelection = function(e) {
23428
+ mouseX = e.clientX;
23429
+ mouseY = e.clientY;
23430
+ };
23431
+
23432
+ var session = editor.session;
23433
+ var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
23434
+ var screenCursor = screenAnchor;
23435
+
23436
+ var selectionMode;
23437
+ if (editor.$mouseHandler.$enableJumpToDef) {
23438
+ if (ctrl && alt || accel && alt)
23439
+ selectionMode = "add";
23440
+ else if (alt)
23441
+ selectionMode = "block";
23442
+ } else {
23443
+ if (accel && !alt) {
23444
+ selectionMode = "add";
23445
+ if (!isMultiSelect && shift)
23446
+ return;
23447
+ } else if (alt) {
23448
+ selectionMode = "block";
23449
+ }
23450
+ }
23451
+
23452
+ if (selectionMode && useragent.isMac && ev.ctrlKey) {
23453
+ editor.$mouseHandler.cancelContextMenu();
23454
+ }
23455
+
23456
+ if (selectionMode == "add") {
23457
+ if (!isMultiSelect && inSelection)
23458
+ return; // dragging
23459
+
23460
+ if (!isMultiSelect) {
23461
+ var range = selection.toOrientedRange();
23462
+ editor.addSelectionMarker(range);
23463
+ }
23464
+
23465
+ var oldRange = selection.rangeList.rangeAtPoint(pos);
23466
+
23467
+
23468
+ editor.$blockScrolling++;
23469
+ editor.inVirtualSelectionMode = true;
23470
+
23471
+ if (shift) {
23472
+ oldRange = null;
23473
+ range = selection.ranges[0];
23474
+ editor.removeSelectionMarker(range);
23475
+ }
23476
+ editor.once("mouseup", function() {
23477
+ var tmpSel = selection.toOrientedRange();
23478
+
23479
+ if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
23480
+ selection.substractPoint(tmpSel.cursor);
23481
+ else {
23482
+ if (shift) {
23483
+ selection.substractPoint(range.cursor);
23484
+ } else if (range) {
23485
+ editor.removeSelectionMarker(range);
23486
+ selection.addRange(range);
23487
+ }
23488
+ selection.addRange(tmpSel);
23489
+ }
23490
+ editor.$blockScrolling--;
23491
+ editor.inVirtualSelectionMode = false;
23492
+ });
23493
+
23494
+ } else if (selectionMode == "block") {
23495
+ e.stop();
23496
+ editor.inVirtualSelectionMode = true;
23497
+ var initialRange;
23498
+ var rectSel = [];
23499
+ var blockSelect = function() {
23500
+ var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
23501
+ var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
23502
+
23503
+ if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead))
23504
+ return;
23505
+ screenCursor = newCursor;
23506
+
23507
+ editor.selection.moveToPosition(cursor);
23508
+ editor.renderer.scrollCursorIntoView();
23509
+
23510
+ editor.removeSelectionMarkers(rectSel);
23511
+ rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
23512
+ if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty())
23513
+ rectSel[0] = editor.$mouseHandler.$clickSelection.clone();
23514
+ rectSel.forEach(editor.addSelectionMarker, editor);
23515
+ editor.updateSelectionMarkers();
23516
+ };
23517
+
23518
+ if (isMultiSelect && !accel) {
23519
+ selection.toSingleRange();
23520
+ } else if (!isMultiSelect && accel) {
23521
+ initialRange = selection.toOrientedRange();
23522
+ editor.addSelectionMarker(initialRange);
23523
+ }
23524
+
23525
+ if (shift)
23526
+ screenAnchor = session.documentToScreenPosition(selection.lead);
23527
+ else
23528
+ selection.moveToPosition(pos);
23529
+
23530
+ screenCursor = {row: -1, column: -1};
23531
+
23532
+ var onMouseSelectionEnd = function(e) {
23533
+ clearInterval(timerId);
23534
+ editor.removeSelectionMarkers(rectSel);
23535
+ if (!rectSel.length)
23536
+ rectSel = [selection.toOrientedRange()];
23537
+ editor.$blockScrolling++;
23538
+ if (initialRange) {
23539
+ editor.removeSelectionMarker(initialRange);
23540
+ selection.toSingleRange(initialRange);
23541
+ }
23542
+ for (var i = 0; i < rectSel.length; i++)
23543
+ selection.addRange(rectSel[i]);
23544
+ editor.inVirtualSelectionMode = false;
23545
+ editor.$mouseHandler.$clickSelection = null;
23546
+ editor.$blockScrolling--;
23547
+ };
23548
+
23549
+ var onSelectionInterval = blockSelect;
23550
+
23551
+ event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
23552
+ var timerId = setInterval(function() {onSelectionInterval();}, 20);
23553
+
23554
+ return e.preventDefault();
23555
+ }
23556
+ }
23557
+
23558
+
23559
+ exports.onMouseDown = onMouseDown;
23560
+
23561
+ });
23562
+
23563
+ ace.define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(acequire, exports, module) {
23564
+ exports.defaultCommands = [{
23565
+ name: "addCursorAbove",
23566
+ exec: function(editor) { editor.selectMoreLines(-1); },
23567
+ bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
23568
+ readonly: true
23569
+ }, {
23570
+ name: "addCursorBelow",
23571
+ exec: function(editor) { editor.selectMoreLines(1); },
23572
+ bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
23573
+ readonly: true
23574
+ }, {
23575
+ name: "addCursorAboveSkipCurrent",
23576
+ exec: function(editor) { editor.selectMoreLines(-1, true); },
23577
+ bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
23578
+ readonly: true
23579
+ }, {
23580
+ name: "addCursorBelowSkipCurrent",
23581
+ exec: function(editor) { editor.selectMoreLines(1, true); },
23582
+ bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
23583
+ readonly: true
23584
+ }, {
23585
+ name: "selectMoreBefore",
23586
+ exec: function(editor) { editor.selectMore(-1); },
23587
+ bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
23588
+ readonly: true
23589
+ }, {
23590
+ name: "selectMoreAfter",
23591
+ exec: function(editor) { editor.selectMore(1); },
23592
+ bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
23593
+ readonly: true
23594
+ }, {
23595
+ name: "selectNextBefore",
23596
+ exec: function(editor) { editor.selectMore(-1, true); },
23597
+ bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
23598
+ readonly: true
23599
+ }, {
23600
+ name: "selectNextAfter",
23601
+ exec: function(editor) { editor.selectMore(1, true); },
23602
+ bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
23603
+ readonly: true
23604
+ }, {
23605
+ name: "splitIntoLines",
23606
+ exec: function(editor) { editor.multiSelect.splitIntoLines(); },
23607
+ bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"},
23608
+ readonly: true
23609
+ }, {
23610
+ name: "alignCursors",
23611
+ exec: function(editor) { editor.alignCursors(); },
23612
+ bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}
23613
+ }, {
23614
+ name: "findAll",
23615
+ exec: function(editor) { editor.findAll(); },
23616
+ bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"},
23617
+ readonly: true
23618
+ }];
23619
+ exports.multiSelectCommands = [{
23620
+ name: "singleSelection",
23621
+ bindKey: "esc",
23622
+ exec: function(editor) { editor.exitMultiSelectMode(); },
23623
+ readonly: true,
23624
+ isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
23625
+ }];
23626
+
23627
+ var HashHandler = acequire("../keyboard/hash_handler").HashHandler;
23628
+ exports.keyboardHandler = new HashHandler(exports.multiSelectCommands);
23629
+
23630
+ });
23631
+
23632
+ ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(acequire, exports, module) {
23633
+
23634
+ var RangeList = acequire("./range_list").RangeList;
23635
+ var Range = acequire("./range").Range;
23636
+ var Selection = acequire("./selection").Selection;
23637
+ var onMouseDown = acequire("./mouse/multi_select_handler").onMouseDown;
23638
+ var event = acequire("./lib/event");
23639
+ var lang = acequire("./lib/lang");
23640
+ var commands = acequire("./commands/multi_select_commands");
23641
+ exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);
23642
+ var Search = acequire("./search").Search;
23643
+ var search = new Search();
23644
+
23645
+ function find(session, needle, dir) {
23646
+ search.$options.wrap = true;
23647
+ search.$options.needle = needle;
23648
+ search.$options.backwards = dir == -1;
23649
+ return search.find(session);
23650
+ }
23651
+ var EditSession = acequire("./edit_session").EditSession;
23652
+ (function() {
23653
+ this.getSelectionMarkers = function() {
23654
+ return this.$selectionMarkers;
23655
+ };
23656
+ }).call(EditSession.prototype);
23657
+ (function() {
23658
+ this.ranges = null;
23659
+ this.rangeList = null;
23660
+ this.addRange = function(range, $blockChangeEvents) {
23661
+ if (!range)
23662
+ return;
23663
+
23664
+ if (!this.inMultiSelectMode && this.rangeCount === 0) {
23665
+ var oldRange = this.toOrientedRange();
23666
+ this.rangeList.add(oldRange);
23667
+ this.rangeList.add(range);
23668
+ if (this.rangeList.ranges.length != 2) {
23669
+ this.rangeList.removeAll();
23670
+ return $blockChangeEvents || this.fromOrientedRange(range);
23671
+ }
23672
+ this.rangeList.removeAll();
23673
+ this.rangeList.add(oldRange);
23674
+ this.$onAddRange(oldRange);
23675
+ }
23676
+
23677
+ if (!range.cursor)
23678
+ range.cursor = range.end;
23679
+
23680
+ var removed = this.rangeList.add(range);
23681
+
23682
+ this.$onAddRange(range);
23683
+
23684
+ if (removed.length)
23685
+ this.$onRemoveRange(removed);
23686
+
23687
+ if (this.rangeCount > 1 && !this.inMultiSelectMode) {
23688
+ this._signal("multiSelect");
23689
+ this.inMultiSelectMode = true;
23690
+ this.session.$undoSelect = false;
23691
+ this.rangeList.attach(this.session);
23692
+ }
23693
+
23694
+ return $blockChangeEvents || this.fromOrientedRange(range);
23695
+ };
23696
+
23697
+ this.toSingleRange = function(range) {
23698
+ range = range || this.ranges[0];
23699
+ var removed = this.rangeList.removeAll();
23700
+ if (removed.length)
23701
+ this.$onRemoveRange(removed);
23702
+
23703
+ range && this.fromOrientedRange(range);
23704
+ };
23705
+ this.substractPoint = function(pos) {
23706
+ var removed = this.rangeList.substractPoint(pos);
23707
+ if (removed) {
23708
+ this.$onRemoveRange(removed);
23709
+ return removed[0];
23710
+ }
23711
+ };
23712
+ this.mergeOverlappingRanges = function() {
23713
+ var removed = this.rangeList.merge();
23714
+ if (removed.length)
23715
+ this.$onRemoveRange(removed);
23716
+ else if(this.ranges[0])
23717
+ this.fromOrientedRange(this.ranges[0]);
23718
+ };
23719
+
23720
+ this.$onAddRange = function(range) {
23721
+ this.rangeCount = this.rangeList.ranges.length;
23722
+ this.ranges.unshift(range);
23723
+ this._signal("addRange", {range: range});
23724
+ };
23725
+
23726
+ this.$onRemoveRange = function(removed) {
23727
+ this.rangeCount = this.rangeList.ranges.length;
23728
+ if (this.rangeCount == 1 && this.inMultiSelectMode) {
23729
+ var lastRange = this.rangeList.ranges.pop();
23730
+ removed.push(lastRange);
23731
+ this.rangeCount = 0;
23732
+ }
23733
+
23734
+ for (var i = removed.length; i--; ) {
23735
+ var index = this.ranges.indexOf(removed[i]);
23736
+ this.ranges.splice(index, 1);
23737
+ }
23738
+
23739
+ this._signal("removeRange", {ranges: removed});
23740
+
23741
+ if (this.rangeCount === 0 && this.inMultiSelectMode) {
23742
+ this.inMultiSelectMode = false;
23743
+ this._signal("singleSelect");
23744
+ this.session.$undoSelect = true;
23745
+ this.rangeList.detach(this.session);
23746
+ }
23747
+
23748
+ lastRange = lastRange || this.ranges[0];
23749
+ if (lastRange && !lastRange.isEqual(this.getRange()))
23750
+ this.fromOrientedRange(lastRange);
23751
+ };
23752
+ this.$initRangeList = function() {
23753
+ if (this.rangeList)
23754
+ return;
23755
+
23756
+ this.rangeList = new RangeList();
23757
+ this.ranges = [];
23758
+ this.rangeCount = 0;
23759
+ };
23760
+ this.getAllRanges = function() {
23761
+ return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()];
23762
+ };
23763
+
23764
+ this.splitIntoLines = function () {
23765
+ if (this.rangeCount > 1) {
23766
+ var ranges = this.rangeList.ranges;
23767
+ var lastRange = ranges[ranges.length - 1];
23768
+ var range = Range.fromPoints(ranges[0].start, lastRange.end);
23769
+
23770
+ this.toSingleRange();
23771
+ this.setSelectionRange(range, lastRange.cursor == lastRange.start);
23772
+ } else {
23773
+ var range = this.getRange();
23774
+ var isBackwards = this.isBackwards();
23775
+ var startRow = range.start.row;
23776
+ var endRow = range.end.row;
23777
+ if (startRow == endRow) {
23778
+ if (isBackwards)
23779
+ var start = range.end, end = range.start;
23780
+ else
23781
+ var start = range.start, end = range.end;
23782
+
23783
+ this.addRange(Range.fromPoints(end, end));
23784
+ this.addRange(Range.fromPoints(start, start));
23785
+ return;
23786
+ }
23787
+
23788
+ var rectSel = [];
23789
+ var r = this.getLineRange(startRow, true);
23790
+ r.start.column = range.start.column;
23791
+ rectSel.push(r);
23792
+
23793
+ for (var i = startRow + 1; i < endRow; i++)
23794
+ rectSel.push(this.getLineRange(i, true));
23795
+
23796
+ r = this.getLineRange(endRow, true);
23797
+ r.end.column = range.end.column;
23798
+ rectSel.push(r);
23799
+
23800
+ rectSel.forEach(this.addRange, this);
23801
+ }
23802
+ };
23803
+ this.toggleBlockSelection = function () {
23804
+ if (this.rangeCount > 1) {
23805
+ var ranges = this.rangeList.ranges;
23806
+ var lastRange = ranges[ranges.length - 1];
23807
+ var range = Range.fromPoints(ranges[0].start, lastRange.end);
23808
+
23809
+ this.toSingleRange();
23810
+ this.setSelectionRange(range, lastRange.cursor == lastRange.start);
23811
+ } else {
23812
+ var cursor = this.session.documentToScreenPosition(this.selectionLead);
23813
+ var anchor = this.session.documentToScreenPosition(this.selectionAnchor);
23814
+
23815
+ var rectSel = this.rectangularRangeBlock(cursor, anchor);
23816
+ rectSel.forEach(this.addRange, this);
23817
+ }
23818
+ };
23819
+ this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {
23820
+ var rectSel = [];
23821
+
23822
+ var xBackwards = screenCursor.column < screenAnchor.column;
23823
+ if (xBackwards) {
23824
+ var startColumn = screenCursor.column;
23825
+ var endColumn = screenAnchor.column;
23826
+ } else {
23827
+ var startColumn = screenAnchor.column;
23828
+ var endColumn = screenCursor.column;
23829
+ }
23830
+
23831
+ var yBackwards = screenCursor.row < screenAnchor.row;
23832
+ if (yBackwards) {
23833
+ var startRow = screenCursor.row;
23834
+ var endRow = screenAnchor.row;
23835
+ } else {
23836
+ var startRow = screenAnchor.row;
23837
+ var endRow = screenCursor.row;
23838
+ }
23839
+
23840
+ if (startColumn < 0)
23841
+ startColumn = 0;
23842
+ if (startRow < 0)
23843
+ startRow = 0;
23844
+
23845
+ if (startRow == endRow)
23846
+ includeEmptyLines = true;
23847
+
23848
+ for (var row = startRow; row <= endRow; row++) {
23849
+ var range = Range.fromPoints(
23850
+ this.session.screenToDocumentPosition(row, startColumn),
23851
+ this.session.screenToDocumentPosition(row, endColumn)
23852
+ );
23853
+ if (range.isEmpty()) {
23854
+ if (docEnd && isSamePoint(range.end, docEnd))
23855
+ break;
23856
+ var docEnd = range.end;
23857
+ }
23858
+ range.cursor = xBackwards ? range.start : range.end;
23859
+ rectSel.push(range);
23860
+ }
23861
+
23862
+ if (yBackwards)
23863
+ rectSel.reverse();
23864
+
23865
+ if (!includeEmptyLines) {
23866
+ var end = rectSel.length - 1;
23867
+ while (rectSel[end].isEmpty() && end > 0)
23868
+ end--;
23869
+ if (end > 0) {
23870
+ var start = 0;
23871
+ while (rectSel[start].isEmpty())
23872
+ start++;
23873
+ }
23874
+ for (var i = end; i >= start; i--) {
23875
+ if (rectSel[i].isEmpty())
23876
+ rectSel.splice(i, 1);
23877
+ }
23878
+ }
23879
+
23880
+ return rectSel;
23881
+ };
23882
+ }).call(Selection.prototype);
23883
+ var Editor = acequire("./editor").Editor;
23884
+ (function() {
23885
+ this.updateSelectionMarkers = function() {
23886
+ this.renderer.updateCursor();
23887
+ this.renderer.updateBackMarkers();
23888
+ };
23889
+ this.addSelectionMarker = function(orientedRange) {
23890
+ if (!orientedRange.cursor)
23891
+ orientedRange.cursor = orientedRange.end;
23892
+
23893
+ var style = this.getSelectionStyle();
23894
+ orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style);
23895
+
23896
+ this.session.$selectionMarkers.push(orientedRange);
23897
+ this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
23898
+ return orientedRange;
23899
+ };
23900
+ this.removeSelectionMarker = function(range) {
23901
+ if (!range.marker)
23902
+ return;
23903
+ this.session.removeMarker(range.marker);
23904
+ var index = this.session.$selectionMarkers.indexOf(range);
23905
+ if (index != -1)
23906
+ this.session.$selectionMarkers.splice(index, 1);
23907
+ this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
23908
+ };
23909
+
23910
+ this.removeSelectionMarkers = function(ranges) {
23911
+ var markerList = this.session.$selectionMarkers;
23912
+ for (var i = ranges.length; i--; ) {
23913
+ var range = ranges[i];
23914
+ if (!range.marker)
23915
+ continue;
23916
+ this.session.removeMarker(range.marker);
23917
+ var index = markerList.indexOf(range);
23918
+ if (index != -1)
23919
+ markerList.splice(index, 1);
23920
+ }
23921
+ this.session.selectionMarkerCount = markerList.length;
23922
+ };
23923
+
23924
+ this.$onAddRange = function(e) {
23925
+ this.addSelectionMarker(e.range);
23926
+ this.renderer.updateCursor();
23927
+ this.renderer.updateBackMarkers();
23928
+ };
23929
+
23930
+ this.$onRemoveRange = function(e) {
23931
+ this.removeSelectionMarkers(e.ranges);
23932
+ this.renderer.updateCursor();
23933
+ this.renderer.updateBackMarkers();
23934
+ };
23935
+
23936
+ this.$onMultiSelect = function(e) {
23937
+ if (this.inMultiSelectMode)
23938
+ return;
23939
+ this.inMultiSelectMode = true;
23940
+
23941
+ this.setStyle("ace_multiselect");
23942
+ this.keyBinding.addKeyboardHandler(commands.keyboardHandler);
23943
+ this.commands.setDefaultHandler("exec", this.$onMultiSelectExec);
23944
+
23945
+ this.renderer.updateCursor();
23946
+ this.renderer.updateBackMarkers();
23947
+ };
23948
+
23949
+ this.$onSingleSelect = function(e) {
23950
+ if (this.session.multiSelect.inVirtualMode)
23951
+ return;
23952
+ this.inMultiSelectMode = false;
23953
+
23954
+ this.unsetStyle("ace_multiselect");
23955
+ this.keyBinding.removeKeyboardHandler(commands.keyboardHandler);
23956
+
23957
+ this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec);
23958
+ this.renderer.updateCursor();
23959
+ this.renderer.updateBackMarkers();
23960
+ this._emit("changeSelection");
23961
+ };
23962
+
23963
+ this.$onMultiSelectExec = function(e) {
23964
+ var command = e.command;
23965
+ var editor = e.editor;
23966
+ if (!editor.multiSelect)
23967
+ return;
23968
+ if (!command.multiSelectAction) {
23969
+ var result = command.exec(editor, e.args || {});
23970
+ editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
23971
+ editor.multiSelect.mergeOverlappingRanges();
23972
+ } else if (command.multiSelectAction == "forEach") {
23973
+ result = editor.forEachSelection(command, e.args);
23974
+ } else if (command.multiSelectAction == "forEachLine") {
23975
+ result = editor.forEachSelection(command, e.args, true);
23976
+ } else if (command.multiSelectAction == "single") {
23977
+ editor.exitMultiSelectMode();
23978
+ result = command.exec(editor, e.args || {});
23979
+ } else {
23980
+ result = command.multiSelectAction(editor, e.args || {});
23981
+ }
23982
+ return result;
23983
+ };
23984
+ this.forEachSelection = function(cmd, args, options) {
23985
+ if (this.inVirtualSelectionMode)
23986
+ return;
23987
+ var keepOrder = options && options.keepOrder;
23988
+ var $byLines = options == true || options && options.$byLines
23989
+ var session = this.session;
23990
+ var selection = this.selection;
23991
+ var rangeList = selection.rangeList;
23992
+ var ranges = (keepOrder ? selection : rangeList).ranges;
23993
+ var result;
23994
+
23995
+ if (!ranges.length)
23996
+ return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});
23997
+
23998
+ var reg = selection._eventRegistry;
23999
+ selection._eventRegistry = {};
24000
+
24001
+ var tmpSel = new Selection(session);
24002
+ this.inVirtualSelectionMode = true;
24003
+ for (var i = ranges.length; i--;) {
24004
+ if ($byLines) {
24005
+ while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row)
24006
+ i--;
24007
+ }
24008
+ tmpSel.fromOrientedRange(ranges[i]);
24009
+ tmpSel.index = i;
24010
+ this.selection = session.selection = tmpSel;
24011
+ var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});
24012
+ if (!result && cmdResult !== undefined)
24013
+ result = cmdResult;
24014
+ tmpSel.toOrientedRange(ranges[i]);
24015
+ }
24016
+ tmpSel.detach();
24017
+
24018
+ this.selection = session.selection = selection;
24019
+ this.inVirtualSelectionMode = false;
24020
+ selection._eventRegistry = reg;
24021
+ selection.mergeOverlappingRanges();
24022
+
24023
+ var anim = this.renderer.$scrollAnimation;
24024
+ this.onCursorChange();
24025
+ this.onSelectionChange();
24026
+ if (anim && anim.from == anim.to)
24027
+ this.renderer.animateScrolling(anim.from);
24028
+
24029
+ return result;
24030
+ };
24031
+ this.exitMultiSelectMode = function() {
24032
+ if (!this.inMultiSelectMode || this.inVirtualSelectionMode)
24033
+ return;
24034
+ this.multiSelect.toSingleRange();
24035
+ };
24036
+
24037
+ this.getSelectedText = function() {
24038
+ var text = "";
24039
+ if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
24040
+ var ranges = this.multiSelect.rangeList.ranges;
24041
+ var buf = [];
24042
+ for (var i = 0; i < ranges.length; i++) {
24043
+ buf.push(this.session.getTextRange(ranges[i]));
24044
+ }
24045
+ var nl = this.session.getDocument().getNewLineCharacter();
24046
+ text = buf.join(nl);
24047
+ if (text.length == (buf.length - 1) * nl.length)
24048
+ text = "";
24049
+ } else if (!this.selection.isEmpty()) {
24050
+ text = this.session.getTextRange(this.getSelectionRange());
24051
+ }
24052
+ return text;
24053
+ };
24054
+
24055
+ this.$checkMultiselectChange = function(e, anchor) {
24056
+ if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
24057
+ var range = this.multiSelect.ranges[0];
24058
+ if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor)
24059
+ return;
24060
+ var pos = anchor == this.multiSelect.anchor
24061
+ ? range.cursor == range.start ? range.end : range.start
24062
+ : range.cursor;
24063
+ if (!isSamePoint(pos, anchor))
24064
+ this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange());
24065
+ }
24066
+ };
24067
+ this.onPaste = function(text) {
24068
+ if (this.$readOnly)
24069
+ return;
24070
+
24071
+
24072
+ var e = {text: text};
24073
+ this._signal("paste", e);
24074
+ text = e.text;
24075
+ if (!this.inMultiSelectMode || this.inVirtualSelectionMode)
24076
+ return this.insert(text);
24077
+
24078
+ var lines = text.split(/\r\n|\r|\n/);
24079
+ var ranges = this.selection.rangeList.ranges;
24080
+
24081
+ if (lines.length > ranges.length || lines.length < 2 || !lines[1])
24082
+ return this.commands.exec("insertstring", this, text);
24083
+
24084
+ for (var i = ranges.length; i--;) {
24085
+ var range = ranges[i];
24086
+ if (!range.isEmpty())
24087
+ this.session.remove(range);
24088
+
24089
+ this.session.insert(range.start, lines[i]);
24090
+ }
24091
+ };
24092
+ this.findAll = function(needle, options, additive) {
24093
+ options = options || {};
24094
+ options.needle = needle || options.needle;
24095
+ if (options.needle == undefined) {
24096
+ var range = this.selection.isEmpty()
24097
+ ? this.selection.getWordRange()
24098
+ : this.selection.getRange();
24099
+ options.needle = this.session.getTextRange(range);
24100
+ }
24101
+ this.$search.set(options);
24102
+
24103
+ var ranges = this.$search.findAll(this.session);
24104
+ if (!ranges.length)
24105
+ return 0;
24106
+
24107
+ this.$blockScrolling += 1;
24108
+ var selection = this.multiSelect;
24109
+
24110
+ if (!additive)
24111
+ selection.toSingleRange(ranges[0]);
24112
+
24113
+ for (var i = ranges.length; i--; )
24114
+ selection.addRange(ranges[i], true);
24115
+ if (range && selection.rangeList.rangeAtPoint(range.start))
24116
+ selection.addRange(range, true);
24117
+
24118
+ this.$blockScrolling -= 1;
24119
+
24120
+ return ranges.length;
24121
+ };
24122
+ this.selectMoreLines = function(dir, skip) {
24123
+ var range = this.selection.toOrientedRange();
24124
+ var isBackwards = range.cursor == range.end;
24125
+
24126
+ var screenLead = this.session.documentToScreenPosition(range.cursor);
24127
+ if (this.selection.$desiredColumn)
24128
+ screenLead.column = this.selection.$desiredColumn;
24129
+
24130
+ var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);
24131
+
24132
+ if (!range.isEmpty()) {
24133
+ var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);
24134
+ var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);
24135
+ } else {
24136
+ var anchor = lead;
24137
+ }
24138
+
24139
+ if (isBackwards) {
24140
+ var newRange = Range.fromPoints(lead, anchor);
24141
+ newRange.cursor = newRange.start;
24142
+ } else {
24143
+ var newRange = Range.fromPoints(anchor, lead);
24144
+ newRange.cursor = newRange.end;
24145
+ }
24146
+
24147
+ newRange.desiredColumn = screenLead.column;
24148
+ if (!this.selection.inMultiSelectMode) {
24149
+ this.selection.addRange(range);
24150
+ } else {
24151
+ if (skip)
24152
+ var toRemove = range.cursor;
24153
+ }
24154
+
24155
+ this.selection.addRange(newRange);
24156
+ if (toRemove)
24157
+ this.selection.substractPoint(toRemove);
24158
+ };
24159
+ this.transposeSelections = function(dir) {
24160
+ var session = this.session;
24161
+ var sel = session.multiSelect;
24162
+ var all = sel.ranges;
24163
+
24164
+ for (var i = all.length; i--; ) {
24165
+ var range = all[i];
24166
+ if (range.isEmpty()) {
24167
+ var tmp = session.getWordRange(range.start.row, range.start.column);
24168
+ range.start.row = tmp.start.row;
24169
+ range.start.column = tmp.start.column;
24170
+ range.end.row = tmp.end.row;
24171
+ range.end.column = tmp.end.column;
24172
+ }
24173
+ }
24174
+ sel.mergeOverlappingRanges();
24175
+
24176
+ var words = [];
24177
+ for (var i = all.length; i--; ) {
24178
+ var range = all[i];
24179
+ words.unshift(session.getTextRange(range));
24180
+ }
24181
+
24182
+ if (dir < 0)
24183
+ words.unshift(words.pop());
24184
+ else
24185
+ words.push(words.shift());
24186
+
24187
+ for (var i = all.length; i--; ) {
24188
+ var range = all[i];
24189
+ var tmp = range.clone();
24190
+ session.replace(range, words[i]);
24191
+ range.start.row = tmp.start.row;
24192
+ range.start.column = tmp.start.column;
24193
+ }
24194
+ };
24195
+ this.selectMore = function(dir, skip, stopAtFirst) {
24196
+ var session = this.session;
24197
+ var sel = session.multiSelect;
24198
+
24199
+ var range = sel.toOrientedRange();
24200
+ if (range.isEmpty()) {
24201
+ range = session.getWordRange(range.start.row, range.start.column);
24202
+ range.cursor = dir == -1 ? range.start : range.end;
24203
+ this.multiSelect.addRange(range);
24204
+ if (stopAtFirst)
24205
+ return;
24206
+ }
24207
+ var needle = session.getTextRange(range);
24208
+
24209
+ var newRange = find(session, needle, dir);
24210
+ if (newRange) {
24211
+ newRange.cursor = dir == -1 ? newRange.start : newRange.end;
24212
+ this.$blockScrolling += 1;
24213
+ this.session.unfold(newRange);
24214
+ this.multiSelect.addRange(newRange);
24215
+ this.$blockScrolling -= 1;
24216
+ this.renderer.scrollCursorIntoView(null, 0.5);
24217
+ }
24218
+ if (skip)
24219
+ this.multiSelect.substractPoint(range.cursor);
24220
+ };
24221
+ this.alignCursors = function() {
24222
+ var session = this.session;
24223
+ var sel = session.multiSelect;
24224
+ var ranges = sel.ranges;
24225
+ var row = -1;
24226
+ var sameRowRanges = ranges.filter(function(r) {
24227
+ if (r.cursor.row == row)
24228
+ return true;
24229
+ row = r.cursor.row;
24230
+ });
24231
+
24232
+ if (!ranges.length || sameRowRanges.length == ranges.length - 1) {
24233
+ var range = this.selection.getRange();
24234
+ var fr = range.start.row, lr = range.end.row;
24235
+ var guessRange = fr == lr;
24236
+ if (guessRange) {
24237
+ var max = this.session.getLength();
24238
+ var line;
24239
+ do {
24240
+ line = this.session.getLine(lr);
24241
+ } while (/[=:]/.test(line) && ++lr < max);
24242
+ do {
24243
+ line = this.session.getLine(fr);
24244
+ } while (/[=:]/.test(line) && --fr > 0);
24245
+
24246
+ if (fr < 0) fr = 0;
24247
+ if (lr >= max) lr = max - 1;
24248
+ }
24249
+ var lines = this.session.doc.removeLines(fr, lr);
24250
+ lines = this.$reAlignText(lines, guessRange);
24251
+ this.session.doc.insert({row: fr, column: 0}, lines.join("\n") + "\n");
24252
+ if (!guessRange) {
24253
+ range.start.column = 0;
24254
+ range.end.column = lines[lines.length - 1].length;
24255
+ }
24256
+ this.selection.setRange(range);
24257
+ } else {
24258
+ sameRowRanges.forEach(function(r) {
24259
+ sel.substractPoint(r.cursor);
24260
+ });
24261
+
24262
+ var maxCol = 0;
24263
+ var minSpace = Infinity;
24264
+ var spaceOffsets = ranges.map(function(r) {
24265
+ var p = r.cursor;
24266
+ var line = session.getLine(p.row);
24267
+ var spaceOffset = line.substr(p.column).search(/\S/g);
24268
+ if (spaceOffset == -1)
24269
+ spaceOffset = 0;
24270
+
24271
+ if (p.column > maxCol)
24272
+ maxCol = p.column;
24273
+ if (spaceOffset < minSpace)
24274
+ minSpace = spaceOffset;
24275
+ return spaceOffset;
24276
+ });
24277
+ ranges.forEach(function(r, i) {
24278
+ var p = r.cursor;
24279
+ var l = maxCol - p.column;
24280
+ var d = spaceOffsets[i] - minSpace;
24281
+ if (l > d)
24282
+ session.insert(p, lang.stringRepeat(" ", l - d));
24283
+ else
24284
+ session.remove(new Range(p.row, p.column, p.row, p.column - l + d));
24285
+
24286
+ r.start.column = r.end.column = maxCol;
24287
+ r.start.row = r.end.row = p.row;
24288
+ r.cursor = r.end;
24289
+ });
24290
+ sel.fromOrientedRange(ranges[0]);
24291
+ this.renderer.updateCursor();
24292
+ this.renderer.updateBackMarkers();
24293
+ }
24294
+ };
24295
+
24296
+ this.$reAlignText = function(lines, forceLeft) {
24297
+ var isLeftAligned = true, isRightAligned = true;
24298
+ var startW, textW, endW;
24299
+
24300
+ return lines.map(function(line) {
24301
+ var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/);
24302
+ if (!m)
24303
+ return [line];
24304
+
24305
+ if (startW == null) {
24306
+ startW = m[1].length;
24307
+ textW = m[2].length;
24308
+ endW = m[3].length;
24309
+ return m;
24310
+ }
24311
+
24312
+ if (startW + textW + endW != m[1].length + m[2].length + m[3].length)
24313
+ isRightAligned = false;
24314
+ if (startW != m[1].length)
24315
+ isLeftAligned = false;
24316
+
24317
+ if (startW > m[1].length)
24318
+ startW = m[1].length;
24319
+ if (textW < m[2].length)
24320
+ textW = m[2].length;
24321
+ if (endW > m[3].length)
24322
+ endW = m[3].length;
24323
+
24324
+ return m;
24325
+ }).map(forceLeft ? alignLeft :
24326
+ isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign);
24327
+
24328
+ function spaces(n) {
24329
+ return lang.stringRepeat(" ", n);
24330
+ }
24331
+
24332
+ function alignLeft(m) {
24333
+ return !m[2] ? m[0] : spaces(startW) + m[2]
24334
+ + spaces(textW - m[2].length + endW)
24335
+ + m[4].replace(/^([=:])\s+/, "$1 ");
24336
+ }
24337
+ function alignRight(m) {
24338
+ return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2]
24339
+ + spaces(endW, " ")
24340
+ + m[4].replace(/^([=:])\s+/, "$1 ");
24341
+ }
24342
+ function unAlign(m) {
24343
+ return !m[2] ? m[0] : spaces(startW) + m[2]
24344
+ + spaces(endW)
24345
+ + m[4].replace(/^([=:])\s+/, "$1 ");
24346
+ }
24347
+ };
24348
+ }).call(Editor.prototype);
24349
+
24350
+
24351
+ function isSamePoint(p1, p2) {
24352
+ return p1.row == p2.row && p1.column == p2.column;
24353
+ }
24354
+ exports.onSessionChange = function(e) {
24355
+ var session = e.session;
24356
+ if (session && !session.multiSelect) {
24357
+ session.$selectionMarkers = [];
24358
+ session.selection.$initRangeList();
24359
+ session.multiSelect = session.selection;
24360
+ }
24361
+ this.multiSelect = session && session.multiSelect;
24362
+
24363
+ var oldSession = e.oldSession;
24364
+ if (oldSession) {
24365
+ oldSession.multiSelect.off("addRange", this.$onAddRange);
24366
+ oldSession.multiSelect.off("removeRange", this.$onRemoveRange);
24367
+ oldSession.multiSelect.off("multiSelect", this.$onMultiSelect);
24368
+ oldSession.multiSelect.off("singleSelect", this.$onSingleSelect);
24369
+ oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange);
24370
+ oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange);
24371
+ }
24372
+
24373
+ if (session) {
24374
+ session.multiSelect.on("addRange", this.$onAddRange);
24375
+ session.multiSelect.on("removeRange", this.$onRemoveRange);
24376
+ session.multiSelect.on("multiSelect", this.$onMultiSelect);
24377
+ session.multiSelect.on("singleSelect", this.$onSingleSelect);
24378
+ session.multiSelect.lead.on("change", this.$checkMultiselectChange);
24379
+ session.multiSelect.anchor.on("change", this.$checkMultiselectChange);
24380
+ }
24381
+
24382
+ if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) {
24383
+ if (session.selection.inMultiSelectMode)
24384
+ this.$onMultiSelect();
24385
+ else
24386
+ this.$onSingleSelect();
24387
+ }
24388
+ };
24389
+ function MultiSelect(editor) {
24390
+ if (editor.$multiselectOnSessionChange)
24391
+ return;
24392
+ editor.$onAddRange = editor.$onAddRange.bind(editor);
24393
+ editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
24394
+ editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
24395
+ editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
24396
+ editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor);
24397
+ editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor);
24398
+
24399
+ editor.$multiselectOnSessionChange(editor);
24400
+ editor.on("changeSession", editor.$multiselectOnSessionChange);
24401
+
24402
+ editor.on("mousedown", onMouseDown);
24403
+ editor.commands.addCommands(commands.defaultCommands);
24404
+
24405
+ addAltCursorListeners(editor);
24406
+ }
24407
+
24408
+ function addAltCursorListeners(editor){
24409
+ var el = editor.textInput.getElement();
24410
+ var altCursor = false;
24411
+ event.addListener(el, "keydown", function(e) {
24412
+ if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) {
24413
+ if (!altCursor) {
24414
+ editor.renderer.setMouseCursor("crosshair");
24415
+ altCursor = true;
24416
+ }
24417
+ } else if (altCursor) {
24418
+ reset();
24419
+ }
24420
+ });
24421
+
24422
+ event.addListener(el, "keyup", reset);
24423
+ event.addListener(el, "blur", reset);
24424
+ function reset(e) {
24425
+ if (altCursor) {
24426
+ editor.renderer.setMouseCursor("");
24427
+ altCursor = false;
24428
+ }
24429
+ }
24430
+ }
24431
+
24432
+ exports.MultiSelect = MultiSelect;
24433
+
24434
+
24435
+ acequire("./config").defineOptions(Editor.prototype, "editor", {
24436
+ enableMultiselect: {
24437
+ set: function(val) {
24438
+ MultiSelect(this);
24439
+ if (val) {
24440
+ this.on("changeSession", this.$multiselectOnSessionChange);
24441
+ this.on("mousedown", onMouseDown);
24442
+ } else {
24443
+ this.off("changeSession", this.$multiselectOnSessionChange);
24444
+ this.off("mousedown", onMouseDown);
24445
+ }
24446
+ },
24447
+ value: true
24448
+ }
24449
+ });
24450
+
24451
+
24452
+
24453
+ });
24454
+
24455
+ ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(acequire, exports, module) {
24456
+ "use strict";
24457
+
24458
+ var Range = acequire("../../range").Range;
24459
+
24460
+ var FoldMode = exports.FoldMode = function() {};
24461
+
24462
+ (function() {
24463
+
24464
+ this.foldingStartMarker = null;
24465
+ this.foldingStopMarker = null;
24466
+ this.getFoldWidget = function(session, foldStyle, row) {
24467
+ var line = session.getLine(row);
24468
+ if (this.foldingStartMarker.test(line))
24469
+ return "start";
24470
+ if (foldStyle == "markbeginend"
24471
+ && this.foldingStopMarker
24472
+ && this.foldingStopMarker.test(line))
24473
+ return "end";
24474
+ return "";
24475
+ };
24476
+
24477
+ this.getFoldWidgetRange = function(session, foldStyle, row) {
24478
+ return null;
24479
+ };
24480
+
24481
+ this.indentationBlock = function(session, row, column) {
24482
+ var re = /\S/;
24483
+ var line = session.getLine(row);
24484
+ var startLevel = line.search(re);
24485
+ if (startLevel == -1)
24486
+ return;
24487
+
24488
+ var startColumn = column || line.length;
24489
+ var maxRow = session.getLength();
24490
+ var startRow = row;
24491
+ var endRow = row;
24492
+
24493
+ while (++row < maxRow) {
24494
+ var level = session.getLine(row).search(re);
24495
+
24496
+ if (level == -1)
24497
+ continue;
24498
+
24499
+ if (level <= startLevel)
24500
+ break;
24501
+
24502
+ endRow = row;
24503
+ }
24504
+
24505
+ if (endRow > startRow) {
24506
+ var endColumn = session.getLine(endRow).length;
24507
+ return new Range(startRow, startColumn, endRow, endColumn);
24508
+ }
24509
+ };
24510
+
24511
+ this.openingBracketBlock = function(session, bracket, row, column, typeRe) {
24512
+ var start = {row: row, column: column + 1};
24513
+ var end = session.$findClosingBracket(bracket, start, typeRe);
24514
+ if (!end)
24515
+ return;
24516
+
24517
+ var fw = session.foldWidgets[end.row];
24518
+ if (fw == null)
24519
+ fw = session.getFoldWidget(end.row);
24520
+
24521
+ if (fw == "start" && end.row > start.row) {
24522
+ end.row --;
24523
+ end.column = session.getLine(end.row).length;
24524
+ }
24525
+ return Range.fromPoints(start, end);
24526
+ };
24527
+
24528
+ this.closingBracketBlock = function(session, bracket, row, column, typeRe) {
24529
+ var end = {row: row, column: column};
24530
+ var start = session.$findOpeningBracket(bracket, end);
24531
+
24532
+ if (!start)
24533
+ return;
24534
+
24535
+ start.column++;
24536
+ end.column--;
24537
+
24538
+ return Range.fromPoints(start, end);
24539
+ };
24540
+ }).call(FoldMode.prototype);
24541
+
24542
+ });
24543
+
24544
+ ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) {
24545
+ "use strict";
24546
+
24547
+ exports.isDark = false;
24548
+ exports.cssClass = "ace-tm";
24549
+ exports.cssText = ".ace-tm .ace_gutter {\
24550
+ background: #f0f0f0;\
24551
+ color: #333;\
24552
+ }\
24553
+ .ace-tm .ace_print-margin {\
24554
+ width: 1px;\
24555
+ background: #e8e8e8;\
24556
+ }\
24557
+ .ace-tm .ace_fold {\
24558
+ background-color: #6B72E6;\
24559
+ }\
24560
+ .ace-tm {\
24561
+ background-color: #FFFFFF;\
24562
+ color: black;\
24563
+ }\
24564
+ .ace-tm .ace_cursor {\
24565
+ color: black;\
24566
+ }\
24567
+ .ace-tm .ace_invisible {\
24568
+ color: rgb(191, 191, 191);\
24569
+ }\
24570
+ .ace-tm .ace_storage,\
24571
+ .ace-tm .ace_keyword {\
24572
+ color: blue;\
24573
+ }\
24574
+ .ace-tm .ace_constant {\
24575
+ color: rgb(197, 6, 11);\
24576
+ }\
24577
+ .ace-tm .ace_constant.ace_buildin {\
24578
+ color: rgb(88, 72, 246);\
24579
+ }\
24580
+ .ace-tm .ace_constant.ace_language {\
24581
+ color: rgb(88, 92, 246);\
24582
+ }\
24583
+ .ace-tm .ace_constant.ace_library {\
24584
+ color: rgb(6, 150, 14);\
24585
+ }\
24586
+ .ace-tm .ace_invalid {\
24587
+ background-color: rgba(255, 0, 0, 0.1);\
24588
+ color: red;\
24589
+ }\
24590
+ .ace-tm .ace_support.ace_function {\
24591
+ color: rgb(60, 76, 114);\
24592
+ }\
24593
+ .ace-tm .ace_support.ace_constant {\
24594
+ color: rgb(6, 150, 14);\
24595
+ }\
24596
+ .ace-tm .ace_support.ace_type,\
24597
+ .ace-tm .ace_support.ace_class {\
24598
+ color: rgb(109, 121, 222);\
24599
+ }\
24600
+ .ace-tm .ace_keyword.ace_operator {\
24601
+ color: rgb(104, 118, 135);\
24602
+ }\
24603
+ .ace-tm .ace_string {\
24604
+ color: rgb(3, 106, 7);\
24605
+ }\
24606
+ .ace-tm .ace_comment {\
24607
+ color: rgb(76, 136, 107);\
24608
+ }\
24609
+ .ace-tm .ace_comment.ace_doc {\
24610
+ color: rgb(0, 102, 255);\
24611
+ }\
24612
+ .ace-tm .ace_comment.ace_doc.ace_tag {\
24613
+ color: rgb(128, 159, 191);\
24614
+ }\
24615
+ .ace-tm .ace_constant.ace_numeric {\
24616
+ color: rgb(0, 0, 205);\
24617
+ }\
24618
+ .ace-tm .ace_variable {\
24619
+ color: rgb(49, 132, 149);\
24620
+ }\
24621
+ .ace-tm .ace_xml-pe {\
24622
+ color: rgb(104, 104, 91);\
24623
+ }\
24624
+ .ace-tm .ace_entity.ace_name.ace_function {\
24625
+ color: #0000A2;\
24626
+ }\
24627
+ .ace-tm .ace_heading {\
24628
+ color: rgb(12, 7, 255);\
24629
+ }\
24630
+ .ace-tm .ace_list {\
24631
+ color:rgb(185, 6, 144);\
24632
+ }\
24633
+ .ace-tm .ace_meta.ace_tag {\
24634
+ color:rgb(0, 22, 142);\
24635
+ }\
24636
+ .ace-tm .ace_string.ace_regex {\
24637
+ color: rgb(255, 0, 0)\
24638
+ }\
24639
+ .ace-tm .ace_marker-layer .ace_selection {\
24640
+ background: rgb(181, 213, 255);\
24641
+ }\
24642
+ .ace-tm.ace_multiselect .ace_selection.ace_start {\
24643
+ box-shadow: 0 0 3px 0px white;\
24644
+ border-radius: 2px;\
24645
+ }\
24646
+ .ace-tm .ace_marker-layer .ace_step {\
24647
+ background: rgb(252, 255, 0);\
24648
+ }\
24649
+ .ace-tm .ace_marker-layer .ace_stack {\
24650
+ background: rgb(164, 229, 101);\
24651
+ }\
24652
+ .ace-tm .ace_marker-layer .ace_bracket {\
24653
+ margin: -1px 0 0 -1px;\
24654
+ border: 1px solid rgb(192, 192, 192);\
24655
+ }\
24656
+ .ace-tm .ace_marker-layer .ace_active-line {\
24657
+ background: rgba(0, 0, 0, 0.07);\
24658
+ }\
24659
+ .ace-tm .ace_gutter-active-line {\
24660
+ background-color : #dcdcdc;\
24661
+ }\
24662
+ .ace-tm .ace_marker-layer .ace_selected-word {\
24663
+ background: rgb(250, 250, 255);\
24664
+ border: 1px solid rgb(200, 200, 250);\
24665
+ }\
24666
+ .ace-tm .ace_indent-guide {\
24667
+ background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\
24668
+ }\
24669
+ ";
24670
+
24671
+ var dom = acequire("../lib/dom");
24672
+ dom.importCssString(exports.cssText, exports.cssClass);
24673
+ });
24674
+
24675
+ ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(acequire, exports, module) {
24676
+ "use strict";
24677
+
24678
+ var oop = acequire("./lib/oop");
24679
+ var dom = acequire("./lib/dom");
24680
+ var Range = acequire("./range").Range;
24681
+
24682
+
24683
+ function LineWidgets(session) {
24684
+ this.session = session;
24685
+ this.session.widgetManager = this;
24686
+ this.session.getRowLength = this.getRowLength;
24687
+ this.session.$getWidgetScreenLength = this.$getWidgetScreenLength;
24688
+ this.updateOnChange = this.updateOnChange.bind(this);
24689
+ this.renderWidgets = this.renderWidgets.bind(this);
24690
+ this.measureWidgets = this.measureWidgets.bind(this);
24691
+ this.session._changedWidgets = [];
24692
+ this.$onChangeEditor = this.$onChangeEditor.bind(this);
24693
+
24694
+ this.session.on("change", this.updateOnChange);
24695
+ this.session.on("changeEditor", this.$onChangeEditor);
24696
+ }
24697
+
24698
+ (function() {
24699
+ this.getRowLength = function(row) {
24700
+ var h;
24701
+ if (this.lineWidgets)
24702
+ h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;
24703
+ else
24704
+ h = 0;
24705
+ if (!this.$useWrapMode || !this.$wrapData[row]) {
24706
+ return 1 + h;
24707
+ } else {
24708
+ return this.$wrapData[row].length + 1 + h;
24709
+ }
24710
+ };
24711
+
24712
+ this.$getWidgetScreenLength = function() {
24713
+ var screenRows = 0;
24714
+ this.lineWidgets.forEach(function(w){
24715
+ if (w && w.rowCount)
24716
+ screenRows +=w.rowCount;
24717
+ });
24718
+ return screenRows;
24719
+ };
24720
+
24721
+ this.$onChangeEditor = function(e) {
24722
+ this.attach(e.editor);
24723
+ };
24724
+
24725
+ this.attach = function(editor) {
24726
+ if (editor && editor.widgetManager && editor.widgetManager != this)
24727
+ editor.widgetManager.detach();
24728
+
24729
+ if (this.editor == editor)
24730
+ return;
24731
+
24732
+ this.detach();
24733
+ this.editor = editor;
24734
+
24735
+ if (editor) {
24736
+ editor.widgetManager = this;
24737
+ editor.renderer.on("beforeRender", this.measureWidgets);
24738
+ editor.renderer.on("afterRender", this.renderWidgets);
24739
+ }
24740
+ };
24741
+ this.detach = function(e) {
24742
+ var editor = this.editor;
24743
+ if (!editor)
24744
+ return;
24745
+
24746
+ this.editor = null;
24747
+ editor.widgetManager = null;
24748
+
24749
+ editor.renderer.off("beforeRender", this.measureWidgets);
24750
+ editor.renderer.off("afterRender", this.renderWidgets);
24751
+ var lineWidgets = this.session.lineWidgets;
24752
+ lineWidgets && lineWidgets.forEach(function(w) {
24753
+ if (w && w.el && w.el.parentNode) {
24754
+ w._inDocument = false;
24755
+ w.el.parentNode.removeChild(w.el);
24756
+ }
24757
+ });
24758
+ };
24759
+
24760
+ this.updateOnChange = function(e) {
24761
+ var lineWidgets = this.session.lineWidgets;
24762
+ if (!lineWidgets) return;
24763
+
24764
+ var delta = e.data;
24765
+ var range = delta.range;
24766
+ var startRow = range.start.row;
24767
+ var len = range.end.row - startRow;
24768
+
24769
+ if (len === 0) {
24770
+ } else if (delta.action == "removeText" || delta.action == "removeLines") {
24771
+ var removed = lineWidgets.splice(startRow + 1, len);
24772
+ removed.forEach(function(w) {
24773
+ w && this.removeLineWidget(w);
24774
+ }, this);
24775
+ this.$updateRows();
24776
+ } else {
24777
+ var args = new Array(len);
24778
+ args.unshift(startRow, 0);
24779
+ lineWidgets.splice.apply(lineWidgets, args);
24780
+ this.$updateRows();
24781
+ }
24782
+ };
24783
+
24784
+ this.$updateRows = function() {
24785
+ var lineWidgets = this.session.lineWidgets;
24786
+ if (!lineWidgets) return;
24787
+ var noWidgets = true;
24788
+ lineWidgets.forEach(function(w, i) {
24789
+ if (w) {
24790
+ noWidgets = false;
24791
+ w.row = i;
24792
+ }
24793
+ });
24794
+ if (noWidgets)
24795
+ this.session.lineWidgets = null;
24796
+ };
24797
+
24798
+ this.addLineWidget = function(w) {
24799
+ if (!this.session.lineWidgets)
24800
+ this.session.lineWidgets = new Array(this.session.getLength());
24801
+
24802
+ this.session.lineWidgets[w.row] = w;
24803
+
24804
+ var renderer = this.editor.renderer;
24805
+ if (w.html && !w.el) {
24806
+ w.el = dom.createElement("div");
24807
+ w.el.innerHTML = w.html;
24808
+ }
24809
+ if (w.el) {
24810
+ dom.addCssClass(w.el, "ace_lineWidgetContainer");
24811
+ w.el.style.position = "absolute";
24812
+ w.el.style.zIndex = 5;
24813
+ renderer.container.appendChild(w.el);
24814
+ w._inDocument = true;
24815
+ }
24816
+
24817
+ if (!w.coverGutter) {
24818
+ w.el.style.zIndex = 3;
24819
+ }
24820
+ if (!w.pixelHeight) {
24821
+ w.pixelHeight = w.el.offsetHeight;
24822
+ }
24823
+ if (w.rowCount == null)
24824
+ w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight;
24825
+
24826
+ this.session._emit("changeFold", {data:{start:{row: w.row}}});
24827
+
24828
+ this.$updateRows();
24829
+ this.renderWidgets(null, renderer);
24830
+ return w;
24831
+ };
24832
+
24833
+ this.removeLineWidget = function(w) {
24834
+ w._inDocument = false;
24835
+ if (w.el && w.el.parentNode)
24836
+ w.el.parentNode.removeChild(w.el);
24837
+ if (w.editor && w.editor.destroy) try {
24838
+ w.editor.destroy();
24839
+ } catch(e){}
24840
+ if (this.session.lineWidgets)
24841
+ this.session.lineWidgets[w.row] = undefined;
24842
+ this.session._emit("changeFold", {data:{start:{row: w.row}}});
24843
+ this.$updateRows();
24844
+ };
24845
+
24846
+ this.onWidgetChanged = function(w) {
24847
+ this.session._changedWidgets.push(w);
24848
+ this.editor && this.editor.renderer.updateFull();
24849
+ };
24850
+
24851
+ this.measureWidgets = function(e, renderer) {
24852
+ var changedWidgets = this.session._changedWidgets;
24853
+ var config = renderer.layerConfig;
24854
+
24855
+ if (!changedWidgets || !changedWidgets.length) return;
24856
+ var min = Infinity;
24857
+ for (var i = 0; i < changedWidgets.length; i++) {
24858
+ var w = changedWidgets[i];
24859
+ if (!w._inDocument) {
24860
+ w._inDocument = true;
24861
+ renderer.container.appendChild(w.el);
24862
+ }
24863
+
24864
+ w.h = w.el.offsetHeight;
24865
+
24866
+ if (!w.fixedWidth) {
24867
+ w.w = w.el.offsetWidth;
24868
+ w.screenWidth = Math.ceil(w.w / config.characterWidth);
24869
+ }
24870
+
24871
+ var rowCount = w.h / config.lineHeight;
24872
+ if (w.coverLine) {
24873
+ rowCount -= this.session.getRowLineCount(w.row);
24874
+ if (rowCount < 0)
24875
+ rowCount = 0;
24876
+ }
24877
+ if (w.rowCount != rowCount) {
24878
+ w.rowCount = rowCount;
24879
+ if (w.row < min)
24880
+ min = w.row;
24881
+ }
24882
+ }
24883
+ if (min != Infinity) {
24884
+ this.session._emit("changeFold", {data:{start:{row: min}}});
24885
+ this.session.lineWidgetWidth = null;
24886
+ }
24887
+ this.session._changedWidgets = [];
24888
+ };
24889
+
24890
+ this.renderWidgets = function(e, renderer) {
24891
+ var config = renderer.layerConfig;
24892
+ var lineWidgets = this.session.lineWidgets;
24893
+ if (!lineWidgets)
24894
+ return;
24895
+ var first = Math.min(this.firstRow, config.firstRow);
24896
+ var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length);
24897
+
24898
+ while (first > 0 && !lineWidgets[first])
24899
+ first--;
24900
+
24901
+ this.firstRow = config.firstRow;
24902
+ this.lastRow = config.lastRow;
24903
+
24904
+ renderer.$cursorLayer.config = config;
24905
+ for (var i = first; i <= last; i++) {
24906
+ var w = lineWidgets[i];
24907
+ if (!w || !w.el) continue;
24908
+
24909
+ if (!w._inDocument) {
24910
+ w._inDocument = true;
24911
+ renderer.container.appendChild(w.el);
24912
+ }
24913
+ var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top;
24914
+ if (!w.coverLine)
24915
+ top += config.lineHeight * this.session.getRowLineCount(w.row);
24916
+ w.el.style.top = top - config.offset + "px";
24917
+
24918
+ var left = w.coverGutter ? 0 : renderer.gutterWidth;
24919
+ if (!w.fixedWidth)
24920
+ left -= renderer.scrollLeft;
24921
+ w.el.style.left = left + "px";
24922
+
24923
+ if (w.fixedWidth) {
24924
+ w.el.style.right = renderer.scrollBar.getWidth() + "px";
24925
+ } else {
24926
+ w.el.style.right = "";
24927
+ }
24928
+ }
24929
+ };
24930
+
24931
+ }).call(LineWidgets.prototype);
24932
+
24933
+
24934
+ exports.LineWidgets = LineWidgets;
24935
+
24936
+ });
24937
+
24938
+ ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(acequire, exports, module) {
24939
+ "use strict";
24940
+ var LineWidgets = acequire("../line_widgets").LineWidgets;
24941
+ var dom = acequire("../lib/dom");
24942
+ var Range = acequire("../range").Range;
24943
+
24944
+ function binarySearch(array, needle, comparator) {
24945
+ var first = 0;
24946
+ var last = array.length - 1;
24947
+
24948
+ while (first <= last) {
24949
+ var mid = (first + last) >> 1;
24950
+ var c = comparator(needle, array[mid]);
24951
+ if (c > 0)
24952
+ first = mid + 1;
24953
+ else if (c < 0)
24954
+ last = mid - 1;
24955
+ else
24956
+ return mid;
24957
+ }
24958
+ return -(first + 1);
24959
+ }
24960
+
24961
+ function findAnnotations(session, row, dir) {
24962
+ var annotations = session.getAnnotations().sort(Range.comparePoints);
24963
+ if (!annotations.length)
24964
+ return;
24965
+
24966
+ var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints);
24967
+ if (i < 0)
24968
+ i = -i - 1;
24969
+
24970
+ if (i >= annotations.length - 1)
24971
+ i = dir > 0 ? 0 : annotations.length - 1;
24972
+ else if (i === 0 && dir < 0)
24973
+ i = annotations.length - 1;
24974
+
24975
+ var annotation = annotations[i];
24976
+ if (!annotation || !dir)
24977
+ return;
24978
+
24979
+ if (annotation.row === row) {
24980
+ do {
24981
+ annotation = annotations[i += dir];
24982
+ } while (annotation && annotation.row === row);
24983
+ if (!annotation)
24984
+ return annotations.slice();
24985
+ }
24986
+
24987
+
24988
+ var matched = [];
24989
+ row = annotation.row;
24990
+ do {
24991
+ matched[dir < 0 ? "unshift" : "push"](annotation);
24992
+ annotation = annotations[i += dir];
24993
+ } while (annotation && annotation.row == row);
24994
+ return matched.length && matched;
24995
+ }
24996
+
24997
+ exports.showErrorMarker = function(editor, dir) {
24998
+ var session = editor.session;
24999
+ if (!session.widgetManager) {
25000
+ session.widgetManager = new LineWidgets(session);
25001
+ session.widgetManager.attach(editor);
25002
+ }
25003
+
25004
+ var pos = editor.getCursorPosition();
25005
+ var row = pos.row;
25006
+ var oldWidget = session.lineWidgets && session.lineWidgets[row];
25007
+ if (oldWidget) {
25008
+ oldWidget.destroy();
25009
+ } else {
25010
+ row -= dir;
25011
+ }
25012
+ var annotations = findAnnotations(session, row, dir);
25013
+ var gutterAnno;
25014
+ if (annotations) {
25015
+ var annotation = annotations[0];
25016
+ pos.column = (annotation.pos && typeof annotation.column != "number"
25017
+ ? annotation.pos.sc
25018
+ : annotation.column) || 0;
25019
+ pos.row = annotation.row;
25020
+ gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row];
25021
+ } else if (oldWidget) {
25022
+ return;
25023
+ } else {
25024
+ gutterAnno = {
25025
+ text: ["Looks good!"],
25026
+ className: "ace_ok"
25027
+ };
25028
+ }
25029
+ editor.session.unfold(pos.row);
25030
+ editor.selection.moveToPosition(pos);
25031
+
25032
+ var w = {
25033
+ row: pos.row,
25034
+ fixedWidth: true,
25035
+ coverGutter: true,
25036
+ el: dom.createElement("div")
25037
+ };
25038
+ var el = w.el.appendChild(dom.createElement("div"));
25039
+ var arrow = w.el.appendChild(dom.createElement("div"));
25040
+ arrow.className = "error_widget_arrow " + gutterAnno.className;
25041
+
25042
+ var left = editor.renderer.$cursorLayer
25043
+ .getPixelPosition(pos).left;
25044
+ arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px";
25045
+
25046
+ w.el.className = "error_widget_wrapper";
25047
+ el.className = "error_widget " + gutterAnno.className;
25048
+ el.innerHTML = gutterAnno.text.join("<br>");
25049
+
25050
+ el.appendChild(dom.createElement("div"));
25051
+
25052
+ var kb = function(_, hashId, keyString) {
25053
+ if (hashId === 0 && (keyString === "esc" || keyString === "return")) {
25054
+ w.destroy();
25055
+ return {command: "null"};
25056
+ }
25057
+ };
25058
+
25059
+ w.destroy = function() {
25060
+ if (editor.$mouseHandler.isMousePressed)
25061
+ return;
25062
+ editor.keyBinding.removeKeyboardHandler(kb);
25063
+ session.widgetManager.removeLineWidget(w);
25064
+ editor.off("changeSelection", w.destroy);
25065
+ editor.off("changeSession", w.destroy);
25066
+ editor.off("mouseup", w.destroy);
25067
+ editor.off("change", w.destroy);
25068
+ };
25069
+
25070
+ editor.keyBinding.addKeyboardHandler(kb);
25071
+ editor.on("changeSelection", w.destroy);
25072
+ editor.on("changeSession", w.destroy);
25073
+ editor.on("mouseup", w.destroy);
25074
+ editor.on("change", w.destroy);
25075
+
25076
+ editor.session.widgetManager.addLineWidget(w);
25077
+
25078
+ w.el.onmousedown = editor.focus.bind(editor);
25079
+
25080
+ editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight});
25081
+ };
25082
+
25083
+
25084
+ dom.importCssString("\
25085
+ .error_widget_wrapper {\
25086
+ background: inherit;\
25087
+ color: inherit;\
25088
+ border:none\
25089
+ }\
25090
+ .error_widget {\
25091
+ border-top: solid 2px;\
25092
+ border-bottom: solid 2px;\
25093
+ margin: 5px 0;\
25094
+ padding: 10px 40px;\
25095
+ white-space: pre-wrap;\
25096
+ }\
25097
+ .error_widget.ace_error, .error_widget_arrow.ace_error{\
25098
+ border-color: #ff5a5a\
25099
+ }\
25100
+ .error_widget.ace_warning, .error_widget_arrow.ace_warning{\
25101
+ border-color: #F1D817\
25102
+ }\
25103
+ .error_widget.ace_info, .error_widget_arrow.ace_info{\
25104
+ border-color: #5a5a5a\
25105
+ }\
25106
+ .error_widget.ace_ok, .error_widget_arrow.ace_ok{\
25107
+ border-color: #5aaa5a\
25108
+ }\
25109
+ .error_widget_arrow {\
25110
+ position: absolute;\
25111
+ border: solid 5px;\
25112
+ border-top-color: transparent!important;\
25113
+ border-right-color: transparent!important;\
25114
+ border-left-color: transparent!important;\
25115
+ top: -5px;\
25116
+ }\
25117
+ ", "");
25118
+
25119
+ });
25120
+
25121
+ ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(acequire, exports, module) {
25122
+ "use strict";
25123
+
25124
+ acequire("./lib/fixoldbrowsers");
25125
+
25126
+ var dom = acequire("./lib/dom");
25127
+ var event = acequire("./lib/event");
25128
+
25129
+ var Editor = acequire("./editor").Editor;
25130
+ var EditSession = acequire("./edit_session").EditSession;
25131
+ var UndoManager = acequire("./undomanager").UndoManager;
25132
+ var Renderer = acequire("./virtual_renderer").VirtualRenderer;
25133
+ acequire("./worker/worker_client");
25134
+ acequire("./keyboard/hash_handler");
25135
+ acequire("./placeholder");
25136
+ acequire("./multi_select");
25137
+ acequire("./mode/folding/fold_mode");
25138
+ acequire("./theme/textmate");
25139
+ acequire("./ext/error_marker");
25140
+
25141
+ exports.config = acequire("./config");
25142
+ exports.acequire = acequire;
25143
+ exports.edit = function(el) {
25144
+ if (typeof(el) == "string") {
25145
+ var _id = el;
25146
+ el = document.getElementById(_id);
25147
+ if (!el)
25148
+ throw new Error("ace.edit can't find div #" + _id);
25149
+ }
25150
+
25151
+ if (el && el.env && el.env.editor instanceof Editor)
25152
+ return el.env.editor;
25153
+
25154
+ var value = "";
25155
+ if (el && /input|textarea/i.test(el.tagName)) {
25156
+ var oldNode = el;
25157
+ value = oldNode.value;
25158
+ el = dom.createElement("pre");
25159
+ oldNode.parentNode.replaceChild(el, oldNode);
25160
+ } else {
25161
+ value = dom.getInnerText(el);
25162
+ el.innerHTML = '';
25163
+ }
25164
+
25165
+ var doc = exports.createEditSession(value);
25166
+
25167
+ var editor = new Editor(new Renderer(el));
25168
+ editor.setSession(doc);
25169
+
25170
+ var env = {
25171
+ document: doc,
25172
+ editor: editor,
25173
+ onResize: editor.resize.bind(editor, null)
25174
+ };
25175
+ if (oldNode) env.textarea = oldNode;
25176
+ event.addListener(window, "resize", env.onResize);
25177
+ editor.on("destroy", function() {
25178
+ event.removeListener(window, "resize", env.onResize);
25179
+ env.editor.container.env = null; // prevent memory leak on old ie
25180
+ });
25181
+ editor.container.env = editor.env = env;
25182
+ return editor;
25183
+ };
25184
+ exports.createEditSession = function(text, mode) {
25185
+ var doc = new EditSession(text, mode);
25186
+ doc.setUndoManager(new UndoManager());
25187
+ return doc;
25188
+ }
25189
+ exports.EditSession = EditSession;
25190
+ exports.UndoManager = UndoManager;
25191
+ });
25192
+ (function() {
25193
+ ace.a