erp_app 3.0.7 → 3.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +23 -0
- data/app/controllers/erp_app/application_controller.rb +1 -0
- data/app/controllers/erp_app/desktop/file_manager/base_controller.rb +33 -23
- data/app/controllers/erp_app/public_controller.rb +2 -3
- data/app/controllers/erp_app/shared/configuration_controller.rb +1 -0
- data/app/controllers/erp_app/shared/notes_controller.rb +1 -0
- data/app/controllers/erp_app/shared/profile_management_controller.rb +22 -0
- data/app/controllers/erp_app/widget_proxy_controller.rb +2 -1
- data/app/models/configuration.rb +7 -0
- data/app/views/erp_app/desktop/base/index.erb +2 -3
- data/app/views/erp_app/login/index.erb +1 -1
- data/app/views/erp_app/mobile/base/index.erb +1 -0
- data/app/views/erp_app/organizer/base/index.erb +2 -3
- data/config/routes.rb +1 -1
- data/lib/active_ext/ext_helpers/column_builder.rb +118 -118
- data/lib/erp_app/config.rb +8 -4
- data/lib/erp_app/extensions/railties/action_view/base.rb +0 -1
- data/lib/erp_app/extensions/railties/action_view/helpers/include_helper.rb +18 -3
- data/lib/erp_app/version.rb +1 -1
- data/lib/erp_app/widgets/base.rb +5 -4
- data/lib/erp_app/widgets/loader.rb +2 -2
- data/public/images/btn/left_panel/left_panel_16x16.png +0 -0
- data/public/images/btn/left_right_panel/left_right_panel_16x16.png +0 -0
- data/public/images/btn/right_panel/right_panel_16x16.png +0 -0
- data/public/images/btn/save/save_16x16.png +0 -0
- data/public/images/btn/save_all/save_all_16x16.png +0 -0
- data/public/javascripts/erp_app/ckeditor/ckeditor.js +138 -135
- data/public/javascripts/erp_app/ckeditor/config.js +1 -1
- data/public/javascripts/erp_app/ckeditor/contents.css +1 -1
- data/public/javascripts/erp_app/ckeditor/lang/_languages.js +1 -1
- data/public/javascripts/erp_app/ckeditor/lang/_translationstatus.txt +62 -59
- data/public/javascripts/erp_app/ckeditor/lang/af.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ar.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/bg.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/bn.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/bs.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ca.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/cs.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/cy.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/da.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/de.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/el.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/en-au.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/en-ca.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/en-gb.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/en.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/eo.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/es.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/et.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/eu.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/fa.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/fi.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/fo.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/fr-ca.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/fr.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/gl.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/gu.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/he.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/hi.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/hr.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/hu.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/id.js +6 -0
- data/public/javascripts/erp_app/ckeditor/lang/is.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/it.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ja.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ka.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/km.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ko.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/lt.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/lv.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/mk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/lang/mn.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ms.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/nb.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/nl.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/no.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/pl.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/pt-br.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/pt.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ro.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ru.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/sk.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/sl.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/sr-latn.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/sr.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/sv.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/th.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/tr.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/lang/uk.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/vi.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/zh-cn.js +2 -2
- data/public/javascripts/erp_app/ckeditor/lang/zh.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/_translationstatus.txt +25 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/cs.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/cy.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/da.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/de.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/el.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/en.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/eo.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/fa.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/fi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/fr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/gu.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/he.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/it.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/mk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/nb.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/nl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/no.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/pt-br.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/ro.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/tr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/vi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/a11yhelp/lang/zh-cn.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/about/dialogs/about.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/adobeair/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/ajax/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/autogrow/plugin.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/bbcode/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/clipboard/dialogs/paste.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/colordialog/dialogs/colordialog.js +3 -3
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/_translationstatus.txt +28 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/bg.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/cs.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/cy.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/da.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/de.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/el.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/en.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/eo.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/et.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/fa.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/fi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/fr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/gu.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/he.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/hr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/it.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/nb.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/nl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/no.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/pl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/pt-br.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/tr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/uk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/vi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/lang/zh-cn.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/devtools/plugin.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/dialog/dialogDefinition.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/div/dialogs/div.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/docprops/dialogs/docprops.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/docprops/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/find/dialogs/find.js +3 -3
- data/public/javascripts/erp_app/ckeditor/plugins/flash/dialogs/flash.js +4 -4
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/button.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/checkbox.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/form.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/hiddenfield.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/radio.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/select.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/textarea.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/forms/dialogs/textfield.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/iframe/dialogs/iframe.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/iframedialog/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/image/dialogs/image.js +9 -9
- data/public/javascripts/erp_app/ckeditor/plugins/inlineeditsave/plugin.js +40 -0
- data/public/javascripts/erp_app/ckeditor/plugins/link/dialogs/anchor.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/link/dialogs/link.js +5 -5
- data/public/javascripts/erp_app/ckeditor/plugins/liststyle/dialogs/liststyle.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/pastefromword/filter/default.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/pastetext/dialogs/pastetext.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/dialogs/placeholder.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/_translationstatus.txt +27 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/bg.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/cs.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/cy.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/da.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/de.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/el.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/en.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/eo.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/et.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/fa.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/fi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/fr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/he.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/hr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/it.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/nb.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/nl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/no.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/pl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/pt-br.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/tr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/uk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/vi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/lang/zh-cn.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/placeholder/plugin.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/preview/preview.html +10 -0
- data/public/javascripts/erp_app/ckeditor/plugins/scayt/dialogs/options.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/scayt/dialogs/toolbar.css +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/smiley/dialogs/smiley.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/dialogs/specialchar.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/_translationstatus.txt +22 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/cs.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/cy.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/de.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/el.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/en.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/eo.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/et.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/fa.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/fi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/fr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/he.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/hr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/it.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/nb.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/nl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/no.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/pt-br.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/tr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/specialchar/lang/zh-cn.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/styles/styles/default.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/stylesheetparser/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/table/dialogs/table.js +5 -5
- data/public/javascripts/erp_app/ckeditor/plugins/tableresize/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/tabletools/dialogs/tableCell.js +3 -3
- data/public/javascripts/erp_app/ckeditor/plugins/templates/dialogs/templates.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/templates/templates/default.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/dialogs/uicolor.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/_translationstatus.txt +28 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/bg.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/cs.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/cy.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/da.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/de.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/el.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/en.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/eo.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/et.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/fa.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/fi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/fr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/he.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/hr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/it.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/mk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/nb.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/nl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/no.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/pl.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/pt-br.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/tr.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/ug.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/uk.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/vi.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/lang/zh-cn.js +6 -0
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/plugin.js +2 -2
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/yui/assets/yui.css +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/uicolor/yui/yui.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/wsc/dialogs/ciframe.html +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/wsc/dialogs/tmpFrameset.html +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/wsc/dialogs/wsc.css +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/wsc/dialogs/wsc.js +1 -1
- data/public/javascripts/erp_app/ckeditor/plugins/xml/plugin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/kama/dialog.css +6 -6
- data/public/javascripts/erp_app/ckeditor/skins/kama/editor.css +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/kama/skin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/kama/templates.css +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/office2003/dialog.css +6 -5
- data/public/javascripts/erp_app/ckeditor/skins/office2003/editor.css +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/office2003/skin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/office2003/templates.css +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/v2/dialog.css +5 -5
- data/public/javascripts/erp_app/ckeditor/skins/v2/editor.css +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/v2/skin.js +1 -1
- data/public/javascripts/erp_app/ckeditor/skins/v2/templates.css +1 -1
- data/public/javascripts/erp_app/ckeditor/themes/default/theme.js +1 -1
- data/public/javascripts/erp_app/ckeditor_example_config_override.js +2 -1
- data/public/javascripts/erp_app/codemirror/LICENSE +5 -1
- data/public/javascripts/erp_app/codemirror/README.md +6 -4
- data/public/javascripts/erp_app/codemirror/{css → doc}/baboon.png +0 -0
- data/public/javascripts/erp_app/codemirror/{css → doc}/baboon_vector.svg +0 -0
- data/public/javascripts/erp_app/codemirror/doc/compress.html +155 -0
- data/public/javascripts/erp_app/codemirror/{css → doc}/docs.css +0 -0
- data/public/javascripts/erp_app/codemirror/doc/internals.html +494 -0
- data/public/javascripts/erp_app/codemirror/{manual.html → doc/manual.html} +465 -167
- data/public/javascripts/erp_app/codemirror/doc/oldrelease.html +267 -0
- data/public/javascripts/erp_app/codemirror/doc/reporting.html +57 -0
- data/public/javascripts/erp_app/codemirror/doc/upgrade_v2.2.html +95 -0
- data/public/javascripts/erp_app/codemirror/keymap/emacs.js +29 -0
- data/public/javascripts/erp_app/codemirror/keymap/vim.js +785 -0
- data/public/javascripts/erp_app/codemirror/lib/codemirror.css +116 -14
- data/public/javascripts/erp_app/codemirror/lib/codemirror.js +2128 -1054
- data/public/javascripts/erp_app/codemirror/lib/util/closetag.js +164 -0
- data/public/javascripts/erp_app/codemirror/lib/util/dialog.css +27 -0
- data/public/javascripts/erp_app/codemirror/lib/util/dialog.js +67 -0
- data/public/javascripts/erp_app/codemirror/lib/util/foldcode.js +196 -0
- data/public/javascripts/erp_app/codemirror/lib/util/formatting.js +299 -0
- data/public/javascripts/erp_app/codemirror/lib/util/javascript-hint.js +134 -0
- data/public/javascripts/erp_app/codemirror/lib/util/loadmode.js +51 -0
- data/public/javascripts/erp_app/codemirror/lib/util/match-highlighter.js +44 -0
- data/public/javascripts/erp_app/codemirror/lib/util/multiplex.js +81 -0
- data/public/javascripts/erp_app/codemirror/lib/{overlay.js → util/overlay.js} +3 -2
- data/public/javascripts/erp_app/codemirror/lib/util/pig-hint.js +123 -0
- data/public/javascripts/erp_app/codemirror/lib/util/runmode.js +49 -0
- data/public/javascripts/erp_app/codemirror/lib/util/search.js +118 -0
- data/public/javascripts/erp_app/codemirror/lib/util/searchcursor.js +117 -0
- data/public/javascripts/erp_app/codemirror/lib/util/simple-hint.css +16 -0
- data/public/javascripts/erp_app/codemirror/lib/util/simple-hint.js +76 -0
- data/public/javascripts/erp_app/codemirror/lib/util/xml-hint.js +137 -0
- data/public/javascripts/erp_app/codemirror/mode/clike/clike.js +50 -17
- data/public/javascripts/erp_app/codemirror/mode/clike/index.html +4 -5
- data/public/javascripts/erp_app/codemirror/mode/clike/scala.html +765 -0
- data/public/javascripts/erp_app/codemirror/mode/clojure/clojure.js +207 -0
- data/public/javascripts/erp_app/codemirror/mode/clojure/index.html +66 -0
- data/public/javascripts/erp_app/codemirror/mode/coffeescript/coffeescript.js +101 -63
- data/public/javascripts/erp_app/codemirror/mode/coffeescript/index.html +9 -4
- data/public/javascripts/erp_app/codemirror/mode/css/css.js +4 -4
- data/public/javascripts/erp_app/codemirror/mode/css/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/diff/diff.js +24 -5
- data/public/javascripts/erp_app/codemirror/mode/diff/index.html +12 -7
- data/public/javascripts/erp_app/codemirror/mode/ecl/ecl.js +203 -0
- data/public/javascripts/erp_app/codemirror/mode/ecl/index.html +42 -0
- data/public/javascripts/erp_app/codemirror/mode/erlang/erlang.js +463 -0
- data/public/javascripts/erp_app/codemirror/mode/erlang/index.html +62 -0
- data/public/javascripts/erp_app/codemirror/mode/gfm/gfm.js +144 -0
- data/public/javascripts/erp_app/codemirror/mode/gfm/index.html +47 -0
- data/public/javascripts/erp_app/codemirror/mode/go/go.js +170 -0
- data/public/javascripts/erp_app/codemirror/mode/go/index.html +72 -0
- data/public/javascripts/erp_app/codemirror/mode/groovy/groovy.js +210 -0
- data/public/javascripts/erp_app/codemirror/mode/groovy/index.html +71 -0
- data/public/javascripts/erp_app/codemirror/mode/haskell/index.html +3 -3
- data/public/javascripts/erp_app/codemirror/mode/haxe/haxe.js +432 -0
- data/public/javascripts/erp_app/codemirror/mode/haxe/index.html +90 -0
- data/public/javascripts/erp_app/codemirror/mode/htmlembedded/htmlembedded.js +68 -0
- data/public/javascripts/erp_app/codemirror/mode/htmlembedded/index.html +49 -0
- data/public/javascripts/erp_app/codemirror/mode/htmlmixed/htmlmixed.js +8 -2
- data/public/javascripts/erp_app/codemirror/mode/htmlmixed/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/javascript/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/javascript/javascript.js +26 -13
- data/public/javascripts/erp_app/codemirror/mode/jinja2/index.html +37 -0
- data/public/javascripts/erp_app/codemirror/mode/jinja2/jinja2.js +42 -0
- data/public/javascripts/erp_app/codemirror/mode/less/index.html +618 -0
- data/public/javascripts/erp_app/codemirror/mode/less/less.js +232 -0
- data/public/javascripts/erp_app/codemirror/mode/lua/index.html +3 -3
- data/public/javascripts/erp_app/codemirror/mode/lua/lua.js +5 -3
- data/public/javascripts/erp_app/codemirror/mode/markdown/index.html +340 -0
- data/public/javascripts/erp_app/codemirror/mode/markdown/markdown.js +268 -0
- data/public/javascripts/erp_app/codemirror/mode/mysql/index.html +41 -0
- data/public/javascripts/erp_app/codemirror/mode/mysql/mysql.js +186 -0
- data/public/javascripts/erp_app/codemirror/mode/ntriples/index.html +32 -0
- data/public/javascripts/erp_app/codemirror/mode/ntriples/ntriples.js +172 -0
- data/public/javascripts/erp_app/codemirror/mode/ocaml/index.html +130 -0
- data/public/javascripts/erp_app/codemirror/mode/ocaml/ocaml.js +114 -0
- data/public/javascripts/erp_app/codemirror/mode/pascal/LICENSE +7 -0
- data/public/javascripts/erp_app/codemirror/mode/pascal/index.html +48 -0
- data/public/javascripts/erp_app/codemirror/mode/pascal/pascal.js +94 -0
- data/public/javascripts/erp_app/codemirror/mode/perl/LICENSE +19 -0
- data/public/javascripts/erp_app/codemirror/mode/perl/index.html +62 -0
- data/public/javascripts/erp_app/codemirror/mode/perl/perl.js +816 -0
- data/public/javascripts/erp_app/codemirror/mode/php/index.html +4 -5
- data/public/javascripts/erp_app/codemirror/mode/php/php.js +62 -27
- data/public/javascripts/erp_app/codemirror/mode/pig/index.html +42 -0
- data/public/javascripts/erp_app/codemirror/mode/pig/pig.js +172 -0
- data/public/javascripts/erp_app/codemirror/mode/plsql/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/plsql/plsql.js +2 -2
- data/public/javascripts/erp_app/codemirror/mode/properties/index.html +40 -0
- data/public/javascripts/erp_app/codemirror/mode/properties/properties.js +63 -0
- data/public/javascripts/erp_app/codemirror/mode/python/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/python/python.js +59 -42
- data/public/javascripts/erp_app/codemirror/mode/r/index.html +5 -5
- data/public/javascripts/erp_app/codemirror/mode/r/r.js +9 -2
- data/public/javascripts/erp_app/codemirror/mode/rpm/changes/changes.js +19 -0
- data/public/javascripts/erp_app/codemirror/mode/rpm/changes/index.html +53 -0
- data/public/javascripts/erp_app/codemirror/mode/rpm/spec/index.html +99 -0
- data/public/javascripts/erp_app/codemirror/mode/rpm/spec/spec.css +5 -0
- data/public/javascripts/erp_app/codemirror/mode/rpm/spec/spec.js +66 -0
- data/public/javascripts/erp_app/codemirror/mode/rst/index.html +4 -5
- data/public/javascripts/erp_app/codemirror/mode/rst/rst.js +15 -22
- data/public/javascripts/erp_app/codemirror/mode/ruby/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/ruby/ruby.js +49 -36
- data/public/javascripts/erp_app/codemirror/mode/rust/index.html +48 -0
- data/public/javascripts/erp_app/codemirror/mode/rust/rust.js +432 -0
- data/public/javascripts/erp_app/codemirror/mode/scheme/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/scheme/scheme.js +71 -23
- data/public/javascripts/erp_app/codemirror/mode/shell/index.html +50 -0
- data/public/javascripts/erp_app/codemirror/mode/shell/shell.js +118 -0
- data/public/javascripts/erp_app/codemirror/mode/smalltalk/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/smalltalk/smalltalk.js +137 -120
- data/public/javascripts/erp_app/codemirror/mode/smarty/index.html +82 -0
- data/public/javascripts/erp_app/codemirror/mode/smarty/smarty.js +148 -0
- data/public/javascripts/erp_app/codemirror/mode/sparql/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/mode/stex/index.html +4 -5
- data/public/javascripts/erp_app/codemirror/mode/stex/stex.js +22 -7
- data/public/javascripts/erp_app/codemirror/mode/stex/test.html +263 -0
- data/public/javascripts/erp_app/codemirror/mode/tiddlywiki/index.html +140 -0
- data/public/javascripts/erp_app/codemirror/mode/tiddlywiki/tiddlywiki.css +14 -0
- data/public/javascripts/erp_app/codemirror/mode/tiddlywiki/tiddlywiki.js +384 -0
- data/public/javascripts/erp_app/codemirror/mode/tiki/index.html +82 -0
- data/public/javascripts/erp_app/codemirror/mode/tiki/tiki.css +26 -0
- data/public/javascripts/erp_app/codemirror/mode/tiki/tiki.js +316 -0
- data/public/javascripts/erp_app/codemirror/mode/vb/LICENSE.txt +21 -0
- data/public/javascripts/erp_app/codemirror/mode/vb/index.html +88 -0
- data/public/javascripts/erp_app/codemirror/mode/vb/vb.js +260 -0
- data/public/javascripts/erp_app/codemirror/mode/vbscript/index.html +42 -0
- data/public/javascripts/erp_app/codemirror/mode/vbscript/vbscript.js +26 -0
- data/public/javascripts/erp_app/codemirror/mode/velocity/index.html +3 -3
- data/public/javascripts/erp_app/codemirror/mode/verilog/index.html +210 -0
- data/public/javascripts/erp_app/codemirror/mode/verilog/verilog.js +194 -0
- data/public/javascripts/erp_app/codemirror/mode/xml/index.html +7 -5
- data/public/javascripts/erp_app/codemirror/mode/xml/xml.js +127 -32
- data/public/javascripts/erp_app/codemirror/mode/xquery/LICENSE +20 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/index.html +222 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/index.html +27 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testBase.js +42 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testEmptySequenceKeyword.js +16 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testMultiAttr.js +16 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testNamespaces.js +91 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testProcessingInstructions.js +16 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/test/testQuotes.js +19 -0
- data/public/javascripts/erp_app/codemirror/mode/xquery/xquery.js +448 -0
- data/public/javascripts/erp_app/codemirror/mode/yaml/index.html +3 -4
- data/public/javascripts/erp_app/codemirror/package.json +29 -0
- data/public/javascripts/erp_app/codemirror/test/driver.js +42 -0
- data/public/javascripts/erp_app/codemirror/test/index.html +55 -0
- data/public/javascripts/erp_app/codemirror/test/mode_test.css +22 -0
- data/public/javascripts/erp_app/codemirror/test/mode_test.js +164 -0
- data/public/javascripts/erp_app/codemirror/test/test.js +467 -0
- data/public/javascripts/erp_app/codemirror/theme/ambiance.css +81 -0
- data/public/javascripts/erp_app/codemirror/theme/blackboard.css +25 -0
- data/public/javascripts/erp_app/codemirror/theme/cobalt.css +18 -0
- data/public/javascripts/erp_app/codemirror/theme/eclipse.css +25 -0
- data/public/javascripts/erp_app/codemirror/theme/elegant.css +3 -2
- data/public/javascripts/erp_app/codemirror/theme/erlang-dark.css +21 -0
- data/public/javascripts/erp_app/codemirror/theme/lesser-dark.css +44 -0
- data/public/javascripts/erp_app/codemirror/theme/monokai.css +28 -0
- data/public/javascripts/erp_app/codemirror/theme/neat.css +4 -3
- data/public/javascripts/erp_app/codemirror/theme/night.css +2 -1
- data/public/javascripts/erp_app/codemirror/theme/rubyblue.css +21 -0
- data/public/javascripts/erp_app/codemirror/theme/vibrant-ink.css +27 -0
- data/public/javascripts/erp_app/codemirror/theme/xq-dark.css +46 -0
- data/public/javascripts/erp_app/codemirror_highlight.js +17 -0
- data/public/javascripts/erp_app/desktop/applications/audit_log_viewer/module.js +1 -57
- data/public/javascripts/erp_app/desktop/applications/control_panel/application_management_panel.js +1 -2
- data/public/javascripts/erp_app/desktop/applications/control_panel/module.js +1 -1
- data/public/javascripts/erp_app/desktop/applications/file_manager/module.js +12 -1
- data/public/javascripts/erp_app/desktop/ext_ux_desktop_module.js +9 -1
- data/public/javascripts/erp_app/jquery_support.js +6 -1
- data/public/javascripts/erp_app/login/window.js +1 -1
- data/public/javascripts/erp_app/organizer/default_menu_tree_panel.js +3 -1
- data/public/javascripts/erp_app/organizer/layout.js +92 -79
- data/public/javascripts/erp_app/organizer/preference_window.js +1 -1
- data/public/javascripts/erp_app/{desktop/applications/audit_log_viewer → shared/audit_log}/audit_log_grid_panel.js +1 -0
- data/public/javascripts/erp_app/{desktop/applications/audit_log_viewer → shared/audit_log}/audit_log_item_grid_panel.js +0 -0
- data/public/javascripts/erp_app/shared/audit_log/audit_log_tab_panel.js +52 -0
- data/public/javascripts/erp_app/shared/compass_ckeditor.js +51 -1
- data/public/javascripts/erp_app/shared/compass_codemirror.js +2 -8
- data/public/javascripts/erp_app/shared/configuration/configuration_panel.js +24 -22
- data/public/javascripts/erp_app/shared/dynamic_editable_grid.js +1 -0
- data/public/javascripts/erp_app/shared/dynamic_editable_grid_loader_panel.js +5 -1
- data/public/javascripts/erp_app/shared/file_manager_tree.js +358 -270
- data/public/javascripts/erp_app/shared/file_upload/Ext.ux.panel.UploadPanel.js +580 -0
- data/public/javascripts/erp_app/shared/file_upload/plupload.flash.swf +0 -0
- data/public/javascripts/erp_app/shared/file_upload/plupload.full.js +2 -0
- data/public/javascripts/erp_app/shared/file_upload/plupload.silverlight.xap +0 -0
- data/public/javascripts/erp_app/shared/file_upload/upload_window.js +19 -212
- data/public/javascripts/erp_app/{desktop/applications/control_panel → shared}/profile_management_panel.js +14 -23
- data/public/javascripts/erp_app/utility.js +340 -272
- data/public/javascripts/erp_app/widgets.js +2 -2
- data/public/javascripts/extjs/MultiCellSelectionModel.js +490 -0
- data/public/javascripts/jquery_plugins/jquery.address.min.js +21 -24
- data/public/stylesheets/erp_app/desktop/base.css +3 -1
- data/public/stylesheets/erp_app/shared/compass-ext-all.css +29 -0
- data/public/stylesheets/erp_app/shared/hover_finger.css +4 -0
- metadata +267 -71
- data/app/controllers/erp_app/desktop/control_panel/profile_management_controller.rb +0 -23
- data/app/models/extensions/party.rb +0 -39
- data/public/images/icons/add/Thumbs.db +0 -0
- data/public/images/icons/calendar/Thumbs.db +0 -0
- data/public/images/icons/copy/Thumbs.db +0 -0
- data/public/images/icons/cut/Thumbs.db +0 -0
- data/public/images/icons/delete/Thumbs.db +0 -0
- data/public/images/icons/edit/Thumbs.db +0 -0
- data/public/images/icons/folder/Thumbs.db +0 -0
- data/public/images/icons/gear/Thumbs.db +0 -0
- data/public/images/icons/globe/Thumbs.db +0 -0
- data/public/images/icons/grid/Thumbs.db +0 -0
- data/public/images/icons/help/Thumbs.db +0 -0
- data/public/images/icons/information/Thumbs.db +0 -0
- data/public/images/icons/key/Thumbs.db +0 -0
- data/public/images/icons/log_out/Thumbs.db +0 -0
- data/public/images/icons/mail/Thumbs.db +0 -0
- data/public/images/icons/new/Thumbs.db +0 -0
- data/public/images/icons/next/Thumbs.db +0 -0
- data/public/images/icons/open/Thumbs.db +0 -0
- data/public/images/icons/paste/Thumbs.db +0 -0
- data/public/images/icons/picture/Thumbs.db +0 -0
- data/public/images/icons/presentation/Thumbs.db +0 -0
- data/public/images/icons/preview/Thumbs.db +0 -0
- data/public/images/icons/previous/Thumbs.db +0 -0
- data/public/images/icons/print/Thumbs.db +0 -0
- data/public/images/icons/properties/Thumbs.db +0 -0
- data/public/images/icons/redo/Thumbs.db +0 -0
- data/public/images/icons/refresh/Thumbs.db +0 -0
- data/public/images/icons/remove/Thumbs.db +0 -0
- data/public/images/icons/rename/Thumbs.db +0 -0
- data/public/images/icons/save/Thumbs.db +0 -0
- data/public/images/icons/search/Thumbs.db +0 -0
- data/public/images/icons/send/Thumbs.db +0 -0
- data/public/images/icons/settings/Thumbs.db +0 -0
- data/public/images/icons/synchronize/Thumbs.db +0 -0
- data/public/images/icons/undo/Thumbs.db +0 -0
- data/public/images/icons/upload/Thumbs.db +0 -0
- data/public/images/icons/user/Thumbs.db +0 -0
- data/public/images/icons/zoom_in/Thumbs.db +0 -0
- data/public/images/icons/zoom_out/Thumbs.db +0 -0
- data/public/javascripts/erp_app/ckeditor/plugins/jwplayer/jwplayer/Thumbs.db +0 -0
- data/public/javascripts/erp_app/codemirror/lib/runmode.js +0 -27
- data/public/javascripts/erp_app/codemirror/mode/diff/diff.css +0 -3
- data/public/javascripts/erp_app/codemirror/mode/rst/rst.css +0 -75
- data/public/javascripts/erp_app/codemirror/mode/xmlpure/index.html +0 -60
- data/public/javascripts/erp_app/codemirror/mode/xmlpure/xmlpure.js +0 -481
- data/public/javascripts/erp_app/codemirror/theme/default.css +0 -19
- data/public/javascripts/erp_app/shared/file_upload/Ext.ux.AwesomeUploader.js +0 -511
- data/public/javascripts/erp_app/shared/file_upload/Ext.ux.AwesomeUploaderLocalization.js +0 -45
- data/public/javascripts/erp_app/shared/file_upload/Ext.ux.XHRUpload.js +0 -138
- data/public/javascripts/erp_app/tinymce/Ext.ux.TinyMCE.js +0 -689
- data/public/javascripts/erp_app/tinymce/center_region.js +0 -611
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
// CodeMirror version 2.32
|
|
2
|
+
//
|
|
1
3
|
// All functions that need access to the editor's state live inside
|
|
2
4
|
// the CodeMirror function. Below that, at the bottom of the file,
|
|
3
5
|
// some utilities are defined.
|
|
4
6
|
|
|
5
7
|
// CodeMirror is the only global var we claim
|
|
6
8
|
var CodeMirror = (function() {
|
|
7
|
-
// This is the function that produces an editor instance.
|
|
9
|
+
// This is the function that produces an editor instance. Its
|
|
8
10
|
// closure is used to store the editor state.
|
|
9
11
|
function CodeMirror(place, givenOptions) {
|
|
10
12
|
// Determine effective options based on given values and defaults.
|
|
@@ -13,158 +15,249 @@ var CodeMirror = (function() {
|
|
|
13
15
|
if (defaults.hasOwnProperty(opt))
|
|
14
16
|
options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
|
|
15
17
|
|
|
16
|
-
var targetDocument = options["document"];
|
|
17
18
|
// The element in which the editor lives.
|
|
18
|
-
var wrapper =
|
|
19
|
-
wrapper.className = "CodeMirror";
|
|
19
|
+
var wrapper = document.createElement("div");
|
|
20
|
+
wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
|
|
20
21
|
// This mess creates the base DOM structure for the editor.
|
|
21
22
|
wrapper.innerHTML =
|
|
22
|
-
'<div style="overflow: hidden; position: relative; width:
|
|
23
|
-
'<textarea style="position: absolute; width:
|
|
24
|
-
|
|
23
|
+
'<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
|
|
24
|
+
'<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
|
|
25
|
+
'autocorrect="off" autocapitalize="off"></textarea></div>' +
|
|
26
|
+
'<div class="CodeMirror-scrollbar">' + // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself.
|
|
27
|
+
'<div class="CodeMirror-scrollbar-inner">' + // The empty scrollbar content, used solely for managing the scrollbar thumb.
|
|
28
|
+
'</div></div>' + // This must be before the scroll area because it's float-right.
|
|
29
|
+
'<div class="CodeMirror-scroll" tabindex="-1">' +
|
|
25
30
|
'<div style="position: relative">' + // Set to the height of the text, causes scrolling
|
|
26
|
-
'<div style="position: absolute; height: 0; width: 0; overflow: hidden;"></div>' +
|
|
27
31
|
'<div style="position: relative">' + // Moved around its parent to cover visible view
|
|
28
32
|
'<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
|
|
29
33
|
// Provides positioning relative to (visible) text origin
|
|
30
|
-
'<div class="CodeMirror-lines"><div style="position: relative">' +
|
|
34
|
+
'<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
|
|
35
|
+
// Used to measure text size
|
|
36
|
+
'<div style="position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"></div>' +
|
|
31
37
|
'<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor
|
|
32
|
-
'<
|
|
38
|
+
'<pre class="CodeMirror-cursor" style="visibility: hidden"> </pre>' + // Used to force a width
|
|
39
|
+
'<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
|
|
33
40
|
'</div></div></div></div></div>';
|
|
34
41
|
if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
|
|
35
42
|
// I've never seen more elegant code in my life.
|
|
36
43
|
var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,
|
|
37
44
|
scroller = wrapper.lastChild, code = scroller.firstChild,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
|
|
46
|
+
lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
|
|
47
|
+
cursor = measure.nextSibling, widthForcer = cursor.nextSibling,
|
|
48
|
+
selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling,
|
|
49
|
+
scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild;
|
|
50
|
+
themeChanged(); keyMapChanged();
|
|
51
|
+
// Needed to hide big blue blinking cursor on Mobile Safari
|
|
52
|
+
if (ios) input.style.width = "0px";
|
|
53
|
+
if (!webkit) scroller.draggable = true;
|
|
54
|
+
lineSpace.style.outline = "none";
|
|
55
|
+
if (options.tabindex != null) input.tabIndex = options.tabindex;
|
|
56
|
+
if (options.autofocus) focusInput();
|
|
43
57
|
if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
|
|
58
|
+
// Needed to handle Tab key in KHTML
|
|
59
|
+
if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
|
|
60
|
+
|
|
61
|
+
// Check for OS X >= 10.7. If so, we need to force a width on the scrollbar, and
|
|
62
|
+
// make it overlap the content. (But we only do this if the scrollbar doesn't already
|
|
63
|
+
// have a natural width. If the mouse is plugged in or the user sets the system pref
|
|
64
|
+
// to always show scrollbars, the scrollbar shouldn't overlap.)
|
|
65
|
+
if (mac_geLion) {
|
|
66
|
+
scrollbar.className += (overlapScrollbars() ? " cm-sb-overlap" : " cm-sb-nonoverlap");
|
|
67
|
+
} else if (ie_lt8) {
|
|
68
|
+
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
|
|
69
|
+
scrollbar.className += " cm-sb-ie7";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check for problem with IE innerHTML not working when we have a
|
|
73
|
+
// P (or similar) parent node.
|
|
74
|
+
try { stringWidth("x"); }
|
|
75
|
+
catch (e) {
|
|
76
|
+
if (e.message.match(/runtime/i))
|
|
77
|
+
e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
|
|
78
|
+
throw e;
|
|
79
|
+
}
|
|
44
80
|
|
|
45
81
|
// Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
|
|
46
82
|
var poll = new Delayed(), highlight = new Delayed(), blinker;
|
|
47
83
|
|
|
48
|
-
// mode holds a mode API object.
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
var mode, lines = [new Line("")], work, history = new History(), focused;
|
|
84
|
+
// mode holds a mode API object. doc is the tree of Line objects,
|
|
85
|
+
// work an array of lines that should be parsed, and history the
|
|
86
|
+
// undo history (instance of History constructor).
|
|
87
|
+
var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused;
|
|
53
88
|
loadMode();
|
|
54
89
|
// The selection. These are always maintained to point at valid
|
|
55
90
|
// positions. Inverted is used to remember that the user is
|
|
56
91
|
// selecting bottom-to-top.
|
|
57
92
|
var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
|
|
58
93
|
// Selection-related flags. shiftSelecting obviously tracks
|
|
59
|
-
// whether the user is holding shift.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
var shiftSelecting, reducedSelection, lastDoubleClick;
|
|
94
|
+
// whether the user is holding shift.
|
|
95
|
+
var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, lastScrollLeft = 0, draggingText,
|
|
96
|
+
overwrite = false, suppressEdits = false;
|
|
63
97
|
// Variables used by startOperation/endOperation to track what
|
|
64
98
|
// happened during the operation.
|
|
65
|
-
var updateInput, changes, textChanged, selectionChanged, leaveInputAlone
|
|
99
|
+
var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
|
|
100
|
+
gutterDirty, callbacks;
|
|
66
101
|
// Current visible range (may be bigger than the view window).
|
|
67
|
-
var
|
|
68
|
-
//
|
|
69
|
-
// textarea, to help figure out whether something changed.
|
|
70
|
-
// bracketHighlighted is used to remember that a backet has been
|
|
102
|
+
var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
|
|
103
|
+
// bracketHighlighted is used to remember that a bracket has been
|
|
71
104
|
// marked.
|
|
72
|
-
var
|
|
105
|
+
var bracketHighlighted;
|
|
73
106
|
// Tracks the maximum line length so that the horizontal scrollbar
|
|
74
107
|
// can be kept static when scrolling.
|
|
75
|
-
var maxLine = "",
|
|
108
|
+
var maxLine = "", updateMaxLine = false, maxLineChanged = true;
|
|
109
|
+
var tabCache = {};
|
|
76
110
|
|
|
77
111
|
// Initialize the content.
|
|
78
112
|
operation(function(){setValue(options.value || ""); updateInput = false;})();
|
|
113
|
+
var history = new History();
|
|
79
114
|
|
|
80
115
|
// Register our event handlers.
|
|
81
116
|
connect(scroller, "mousedown", operation(onMouseDown));
|
|
117
|
+
connect(scroller, "dblclick", operation(onDoubleClick));
|
|
118
|
+
connect(lineSpace, "selectstart", e_preventDefault);
|
|
82
119
|
// Gecko browsers fire contextmenu *after* opening the menu, at
|
|
83
120
|
// which point we can't mess with it anymore. Context menu is
|
|
84
121
|
// handled in onMouseDown for Gecko.
|
|
85
122
|
if (!gecko) connect(scroller, "contextmenu", onContextMenu);
|
|
86
|
-
connect(
|
|
87
|
-
connect(
|
|
123
|
+
connect(scroller, "scroll", onScroll);
|
|
124
|
+
connect(scrollbar, "scroll", onScroll);
|
|
125
|
+
connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);});
|
|
126
|
+
connect(scroller, "mousewheel", onMouseWheel);
|
|
127
|
+
connect(scroller, "DOMMouseScroll", onMouseWheel);
|
|
88
128
|
connect(window, "resize", function() {updateDisplay(true);});
|
|
89
129
|
connect(input, "keyup", operation(onKeyUp));
|
|
130
|
+
connect(input, "input", fastPoll);
|
|
90
131
|
connect(input, "keydown", operation(onKeyDown));
|
|
91
132
|
connect(input, "keypress", operation(onKeyPress));
|
|
92
133
|
connect(input, "focus", onFocus);
|
|
93
134
|
connect(input, "blur", onBlur);
|
|
94
135
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
136
|
+
if (options.dragDrop) {
|
|
137
|
+
connect(scroller, "dragstart", onDragStart);
|
|
138
|
+
function drag_(e) {
|
|
139
|
+
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
|
140
|
+
e_stop(e);
|
|
141
|
+
}
|
|
142
|
+
connect(scroller, "dragenter", drag_);
|
|
143
|
+
connect(scroller, "dragover", drag_);
|
|
144
|
+
connect(scroller, "drop", operation(onDrop));
|
|
145
|
+
}
|
|
98
146
|
connect(scroller, "paste", function(){focusInput(); fastPoll();});
|
|
99
|
-
connect(input, "paste",
|
|
100
|
-
connect(input, "cut", function(){
|
|
101
|
-
|
|
102
|
-
|
|
147
|
+
connect(input, "paste", fastPoll);
|
|
148
|
+
connect(input, "cut", operation(function(){
|
|
149
|
+
if (!options.readOnly) replaceSelection("");
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
// Needed to handle Tab key in KHTML
|
|
153
|
+
if (khtml) connect(code, "mouseup", function() {
|
|
154
|
+
if (document.activeElement == input) input.blur();
|
|
155
|
+
focusInput();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// IE throws unspecified error in certain cases, when
|
|
103
159
|
// trying to access activeElement before onload
|
|
104
|
-
var hasFocus; try { hasFocus = (
|
|
105
|
-
if (hasFocus) setTimeout(onFocus, 20);
|
|
160
|
+
var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }
|
|
161
|
+
if (hasFocus || options.autofocus) setTimeout(onFocus, 20);
|
|
106
162
|
else onBlur();
|
|
107
163
|
|
|
108
|
-
function isLine(l) {return l >= 0 && l <
|
|
164
|
+
function isLine(l) {return l >= 0 && l < doc.size;}
|
|
109
165
|
// The instance object that we'll return. Mostly calls out to
|
|
110
166
|
// local functions in the CodeMirror function. Some do some extra
|
|
111
167
|
// range checking and/or clipping. operation is used to wrap the
|
|
112
168
|
// call so that changes it makes are tracked, and the display is
|
|
113
169
|
// updated afterwards.
|
|
114
|
-
var instance = {
|
|
170
|
+
var instance = wrapper.CodeMirror = {
|
|
115
171
|
getValue: getValue,
|
|
116
172
|
setValue: operation(setValue),
|
|
117
173
|
getSelection: getSelection,
|
|
118
174
|
replaceSelection: operation(replaceSelection),
|
|
119
|
-
focus: function(){focusInput(); onFocus(); fastPoll();},
|
|
175
|
+
focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
|
|
120
176
|
setOption: function(option, value) {
|
|
177
|
+
var oldVal = options[option];
|
|
121
178
|
options[option] = value;
|
|
122
|
-
if (option == "
|
|
123
|
-
else if (option == "
|
|
124
|
-
else if (option == "readOnly" && value
|
|
125
|
-
else if (option == "theme")
|
|
179
|
+
if (option == "mode" || option == "indentUnit") loadMode();
|
|
180
|
+
else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
|
|
181
|
+
else if (option == "readOnly" && !value) {resetInput(true);}
|
|
182
|
+
else if (option == "theme") themeChanged();
|
|
183
|
+
else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
|
|
184
|
+
else if (option == "tabSize") updateDisplay(true);
|
|
185
|
+
else if (option == "keyMap") keyMapChanged();
|
|
186
|
+
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
|
|
187
|
+
gutterChanged();
|
|
188
|
+
updateDisplay(true);
|
|
189
|
+
}
|
|
126
190
|
},
|
|
127
191
|
getOption: function(option) {return options[option];},
|
|
128
192
|
undo: operation(undo),
|
|
129
193
|
redo: operation(redo),
|
|
130
194
|
indentLine: operation(function(n, dir) {
|
|
131
|
-
if (
|
|
195
|
+
if (typeof dir != "string") {
|
|
196
|
+
if (dir == null) dir = options.smartIndent ? "smart" : "prev";
|
|
197
|
+
else dir = dir ? "add" : "subtract";
|
|
198
|
+
}
|
|
199
|
+
if (isLine(n)) indentLine(n, dir);
|
|
132
200
|
}),
|
|
201
|
+
indentSelection: operation(indentSelected),
|
|
133
202
|
historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
|
|
203
|
+
clearHistory: function() {history = new History();},
|
|
204
|
+
setHistory: function(histData) {
|
|
205
|
+
history = new History();
|
|
206
|
+
history.done = histData.done;
|
|
207
|
+
history.undone = histData.undone;
|
|
208
|
+
},
|
|
209
|
+
getHistory: function() {
|
|
210
|
+
history.time = 0;
|
|
211
|
+
return {done: history.done.concat([]), undone: history.undone.concat([])};
|
|
212
|
+
},
|
|
134
213
|
matchBrackets: operation(function(){matchBrackets(true);}),
|
|
135
|
-
getTokenAt: function(pos) {
|
|
214
|
+
getTokenAt: operation(function(pos) {
|
|
136
215
|
pos = clipPos(pos);
|
|
137
|
-
return
|
|
138
|
-
},
|
|
216
|
+
return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);
|
|
217
|
+
}),
|
|
139
218
|
getStateAfter: function(line) {
|
|
140
|
-
line = clipLine(line == null ?
|
|
219
|
+
line = clipLine(line == null ? doc.size - 1: line);
|
|
141
220
|
return getStateBefore(line + 1);
|
|
142
221
|
},
|
|
143
|
-
cursorCoords: function(start){
|
|
222
|
+
cursorCoords: function(start, mode) {
|
|
144
223
|
if (start == null) start = sel.inverted;
|
|
145
|
-
return
|
|
224
|
+
return this.charCoords(start ? sel.from : sel.to, mode);
|
|
225
|
+
},
|
|
226
|
+
charCoords: function(pos, mode) {
|
|
227
|
+
pos = clipPos(pos);
|
|
228
|
+
if (mode == "local") return localCoords(pos, false);
|
|
229
|
+
if (mode == "div") return localCoords(pos, true);
|
|
230
|
+
return pageCoords(pos);
|
|
146
231
|
},
|
|
147
|
-
charCoords: function(pos){return pageCoords(clipPos(pos));},
|
|
148
232
|
coordsChar: function(coords) {
|
|
149
233
|
var off = eltOffset(lineSpace);
|
|
150
|
-
|
|
151
|
-
return clipPos({line: line, ch: charFromX(clipLine(line), coords.x - off.left)});
|
|
234
|
+
return coordsChar(coords.x - off.left, coords.y - off.top);
|
|
152
235
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
236
|
+
markText: operation(markText),
|
|
237
|
+
setBookmark: setBookmark,
|
|
238
|
+
findMarksAt: findMarksAt,
|
|
239
|
+
setMarker: operation(addGutterMarker),
|
|
240
|
+
clearMarker: operation(removeGutterMarker),
|
|
157
241
|
setLineClass: operation(setLineClass),
|
|
242
|
+
hideLine: operation(function(h) {return setLineHidden(h, true);}),
|
|
243
|
+
showLine: operation(function(h) {return setLineHidden(h, false);}),
|
|
244
|
+
onDeleteLine: function(line, f) {
|
|
245
|
+
if (typeof line == "number") {
|
|
246
|
+
if (!isLine(line)) return null;
|
|
247
|
+
line = getLine(line);
|
|
248
|
+
}
|
|
249
|
+
(line.handlers || (line.handlers = [])).push(f);
|
|
250
|
+
return line;
|
|
251
|
+
},
|
|
158
252
|
lineInfo: lineInfo,
|
|
159
|
-
addWidget: function(pos, node, scroll,
|
|
253
|
+
addWidget: function(pos, node, scroll, vert, horiz) {
|
|
160
254
|
pos = localCoords(clipPos(pos));
|
|
161
255
|
var top = pos.yBot, left = pos.x;
|
|
162
256
|
node.style.position = "absolute";
|
|
163
257
|
code.appendChild(node);
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
var vspace = Math.max(scroller.offsetHeight, lines.length * lineHeight()),
|
|
258
|
+
if (vert == "over") top = pos.y;
|
|
259
|
+
else if (vert == "near") {
|
|
260
|
+
var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
|
|
168
261
|
hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
|
|
169
262
|
if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
|
|
170
263
|
top = pos.y - node.offsetHeight;
|
|
@@ -172,75 +265,166 @@ var CodeMirror = (function() {
|
|
|
172
265
|
left = hspace - node.offsetWidth;
|
|
173
266
|
}
|
|
174
267
|
node.style.top = (top + paddingTop()) + "px";
|
|
175
|
-
node.style.left =
|
|
268
|
+
node.style.left = node.style.right = "";
|
|
269
|
+
if (horiz == "right") {
|
|
270
|
+
left = code.clientWidth - node.offsetWidth;
|
|
271
|
+
node.style.right = "0px";
|
|
272
|
+
} else {
|
|
273
|
+
if (horiz == "left") left = 0;
|
|
274
|
+
else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2;
|
|
275
|
+
node.style.left = (left + paddingLeft()) + "px";
|
|
276
|
+
}
|
|
176
277
|
if (scroll)
|
|
177
278
|
scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
|
|
178
279
|
},
|
|
179
280
|
|
|
180
|
-
lineCount: function() {return
|
|
281
|
+
lineCount: function() {return doc.size;},
|
|
282
|
+
clipPos: clipPos,
|
|
181
283
|
getCursor: function(start) {
|
|
182
284
|
if (start == null) start = sel.inverted;
|
|
183
285
|
return copyPos(start ? sel.from : sel.to);
|
|
184
286
|
},
|
|
185
287
|
somethingSelected: function() {return !posEq(sel.from, sel.to);},
|
|
186
|
-
setCursor: operation(function(line, ch) {
|
|
187
|
-
if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch);
|
|
188
|
-
else setCursor(line, ch);
|
|
288
|
+
setCursor: operation(function(line, ch, user) {
|
|
289
|
+
if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user);
|
|
290
|
+
else setCursor(line, ch, user);
|
|
189
291
|
}),
|
|
190
|
-
setSelection: operation(function(from, to) {
|
|
191
|
-
|
|
292
|
+
setSelection: operation(function(from, to, user) {
|
|
293
|
+
(user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));
|
|
294
|
+
}),
|
|
295
|
+
getLine: function(line) {if (isLine(line)) return getLine(line).text;},
|
|
296
|
+
getLineHandle: function(line) {if (isLine(line)) return getLine(line);},
|
|
192
297
|
setLine: operation(function(line, text) {
|
|
193
|
-
if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch:
|
|
298
|
+
if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
|
|
194
299
|
}),
|
|
195
300
|
removeLine: operation(function(line) {
|
|
196
301
|
if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
|
|
197
302
|
}),
|
|
198
303
|
replaceRange: operation(replaceRange),
|
|
199
|
-
getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
|
|
304
|
+
getRange: function(from, to, lineSep) {return getRange(clipPos(from), clipPos(to), lineSep);},
|
|
305
|
+
|
|
306
|
+
triggerOnKeyDown: operation(onKeyDown),
|
|
307
|
+
execCommand: function(cmd) {return commands[cmd](instance);},
|
|
308
|
+
// Stuff used by commands, probably not much use to outside code.
|
|
309
|
+
moveH: operation(moveH),
|
|
310
|
+
deleteH: operation(deleteH),
|
|
311
|
+
moveV: operation(moveV),
|
|
312
|
+
toggleOverwrite: function() {
|
|
313
|
+
if(overwrite){
|
|
314
|
+
overwrite = false;
|
|
315
|
+
cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
|
|
316
|
+
} else {
|
|
317
|
+
overwrite = true;
|
|
318
|
+
cursor.className += " CodeMirror-overwrite";
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
posFromIndex: function(off) {
|
|
323
|
+
var lineNo = 0, ch;
|
|
324
|
+
doc.iter(0, doc.size, function(line) {
|
|
325
|
+
var sz = line.text.length + 1;
|
|
326
|
+
if (sz > off) { ch = off; return true; }
|
|
327
|
+
off -= sz;
|
|
328
|
+
++lineNo;
|
|
329
|
+
});
|
|
330
|
+
return clipPos({line: lineNo, ch: ch});
|
|
331
|
+
},
|
|
332
|
+
indexFromPos: function (coords) {
|
|
333
|
+
if (coords.line < 0 || coords.ch < 0) return 0;
|
|
334
|
+
var index = coords.ch;
|
|
335
|
+
doc.iter(0, coords.line, function (line) {
|
|
336
|
+
index += line.text.length + 1;
|
|
337
|
+
});
|
|
338
|
+
return index;
|
|
339
|
+
},
|
|
340
|
+
scrollTo: function(x, y) {
|
|
341
|
+
if (x != null) scroller.scrollLeft = x;
|
|
342
|
+
if (y != null) scrollbar.scrollTop = y;
|
|
343
|
+
updateDisplay([]);
|
|
344
|
+
},
|
|
345
|
+
getScrollInfo: function() {
|
|
346
|
+
return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
|
|
347
|
+
height: scrollbar.scrollHeight, width: scroller.scrollWidth};
|
|
348
|
+
},
|
|
349
|
+
setSize: function(width, height) {
|
|
350
|
+
function interpret(val) {
|
|
351
|
+
val = String(val);
|
|
352
|
+
return /^\d+$/.test(val) ? val + "px" : val;
|
|
353
|
+
}
|
|
354
|
+
if (width != null) wrapper.style.width = interpret(width);
|
|
355
|
+
if (height != null) scroller.style.height = interpret(height);
|
|
356
|
+
},
|
|
200
357
|
|
|
201
358
|
operation: function(f){return operation(f)();},
|
|
202
|
-
|
|
359
|
+
compoundChange: function(f){return compoundChange(f);},
|
|
360
|
+
refresh: function(){
|
|
361
|
+
updateDisplay(true, null, lastScrollTop);
|
|
362
|
+
if (scrollbar.scrollHeight > lastScrollTop)
|
|
363
|
+
scrollbar.scrollTop = lastScrollTop;
|
|
364
|
+
},
|
|
203
365
|
getInputField: function(){return input;},
|
|
204
366
|
getWrapperElement: function(){return wrapper;},
|
|
205
367
|
getScrollerElement: function(){return scroller;},
|
|
206
368
|
getGutterElement: function(){return gutter;}
|
|
207
369
|
};
|
|
208
370
|
|
|
371
|
+
function getLine(n) { return getLineAt(doc, n); }
|
|
372
|
+
function updateLineHeight(line, height) {
|
|
373
|
+
gutterDirty = true;
|
|
374
|
+
var diff = height - line.height;
|
|
375
|
+
for (var n = line; n; n = n.parent) n.height += diff;
|
|
376
|
+
}
|
|
377
|
+
|
|
209
378
|
function setValue(code) {
|
|
210
|
-
history = null;
|
|
211
379
|
var top = {line: 0, ch: 0};
|
|
212
|
-
updateLines(top, {line:
|
|
380
|
+
updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},
|
|
213
381
|
splitLines(code), top, top);
|
|
214
|
-
|
|
382
|
+
updateInput = true;
|
|
215
383
|
}
|
|
216
|
-
function getValue(
|
|
384
|
+
function getValue(lineSep) {
|
|
217
385
|
var text = [];
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
386
|
+
doc.iter(0, doc.size, function(line) { text.push(line.text); });
|
|
387
|
+
return text.join(lineSep || "\n");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function onScroll(e) {
|
|
391
|
+
if (scroller.scrollTop) {
|
|
392
|
+
scrollbar.scrollTop += scroller.scrollTop;
|
|
393
|
+
scroller.scrollTop = 0;
|
|
394
|
+
}
|
|
395
|
+
if (lastScrollTop != scrollbar.scrollTop || lastScrollLeft != scroller.scrollLeft) {
|
|
396
|
+
lastScrollTop = scrollbar.scrollTop;
|
|
397
|
+
lastScrollLeft = scroller.scrollLeft;
|
|
398
|
+
updateDisplay([]);
|
|
399
|
+
if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
|
|
400
|
+
if (options.onScroll) options.onScroll(instance);
|
|
401
|
+
}
|
|
221
402
|
}
|
|
222
403
|
|
|
223
404
|
function onMouseDown(e) {
|
|
405
|
+
setShift(e_prop(e, "shiftKey"));
|
|
224
406
|
// Check whether this is a click in a widget
|
|
225
407
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
226
408
|
if (n.parentNode == code && n != mover) return;
|
|
227
|
-
|
|
228
|
-
//
|
|
409
|
+
|
|
410
|
+
// See if this is a click in the gutter
|
|
229
411
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
230
412
|
if (n.parentNode == gutterText) {
|
|
231
413
|
if (options.onGutterClick)
|
|
232
|
-
options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
|
|
414
|
+
options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);
|
|
233
415
|
return e_preventDefault(e);
|
|
234
416
|
}
|
|
235
417
|
|
|
236
418
|
var start = posFromMouse(e);
|
|
237
|
-
|
|
419
|
+
|
|
238
420
|
switch (e_button(e)) {
|
|
239
421
|
case 3:
|
|
240
|
-
if (gecko
|
|
422
|
+
if (gecko) onContextMenu(e);
|
|
241
423
|
return;
|
|
242
424
|
case 2:
|
|
243
425
|
if (start) setCursor(start.line, start.ch, true);
|
|
426
|
+
setTimeout(focusInput, 20);
|
|
427
|
+
e_preventDefault(e);
|
|
244
428
|
return;
|
|
245
429
|
}
|
|
246
430
|
// For button 1, if it was clicked inside the editor
|
|
@@ -249,24 +433,67 @@ var CodeMirror = (function() {
|
|
|
249
433
|
if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
|
|
250
434
|
|
|
251
435
|
if (!focused) onFocus();
|
|
252
|
-
e_preventDefault(e);
|
|
253
|
-
if (ld && +new Date - ld < 400) return selectLine(start.line);
|
|
254
436
|
|
|
255
|
-
|
|
437
|
+
var now = +new Date, type = "single";
|
|
438
|
+
if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
|
|
439
|
+
type = "triple";
|
|
440
|
+
e_preventDefault(e);
|
|
441
|
+
setTimeout(focusInput, 20);
|
|
442
|
+
selectLine(start.line);
|
|
443
|
+
} else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
|
|
444
|
+
type = "double";
|
|
445
|
+
lastDoubleClick = {time: now, pos: start};
|
|
446
|
+
e_preventDefault(e);
|
|
447
|
+
var word = findWordAt(start);
|
|
448
|
+
setSelectionUser(word.from, word.to);
|
|
449
|
+
} else { lastClick = {time: now, pos: start}; }
|
|
450
|
+
|
|
256
451
|
var last = start, going;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
452
|
+
if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
|
|
453
|
+
!posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
|
|
454
|
+
// Let the drag handler handle this.
|
|
455
|
+
if (webkit) scroller.draggable = true;
|
|
456
|
+
function dragEnd(e2) {
|
|
457
|
+
if (webkit) scroller.draggable = false;
|
|
458
|
+
draggingText = false;
|
|
459
|
+
up(); drop();
|
|
460
|
+
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
|
461
|
+
e_preventDefault(e2);
|
|
462
|
+
setCursor(start.line, start.ch, true);
|
|
463
|
+
focusInput();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
var up = connect(document, "mouseup", operation(dragEnd), true);
|
|
467
|
+
var drop = connect(scroller, "drop", operation(dragEnd), true);
|
|
468
|
+
draggingText = true;
|
|
469
|
+
// IE's approach to draggable
|
|
470
|
+
if (scroller.dragDrop) scroller.dragDrop();
|
|
471
|
+
return;
|
|
263
472
|
}
|
|
473
|
+
e_preventDefault(e);
|
|
474
|
+
if (type == "single") setCursor(start.line, start.ch, true);
|
|
475
|
+
|
|
476
|
+
var startstart = sel.from, startend = sel.to;
|
|
477
|
+
|
|
478
|
+
function doSelect(cur) {
|
|
479
|
+
if (type == "single") {
|
|
480
|
+
setSelectionUser(start, cur);
|
|
481
|
+
} else if (type == "double") {
|
|
482
|
+
var word = findWordAt(cur);
|
|
483
|
+
if (posLess(cur, startstart)) setSelectionUser(word.from, startend);
|
|
484
|
+
else setSelectionUser(startstart, word.to);
|
|
485
|
+
} else if (type == "triple") {
|
|
486
|
+
if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({line: cur.line, ch: 0}));
|
|
487
|
+
else setSelectionUser(startstart, clipPos({line: cur.line + 1, ch: 0}));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
264
491
|
function extend(e) {
|
|
265
492
|
var cur = posFromMouse(e, true);
|
|
266
493
|
if (cur && !posEq(cur, last)) {
|
|
267
494
|
if (!focused) onFocus();
|
|
268
495
|
last = cur;
|
|
269
|
-
|
|
496
|
+
doSelect(cur);
|
|
270
497
|
updateInput = false;
|
|
271
498
|
var visible = visibleLines();
|
|
272
499
|
if (cur.line >= visible.to || cur.line < visible.from)
|
|
@@ -274,27 +501,30 @@ var CodeMirror = (function() {
|
|
|
274
501
|
}
|
|
275
502
|
}
|
|
276
503
|
|
|
277
|
-
|
|
504
|
+
function done(e) {
|
|
278
505
|
clearTimeout(going);
|
|
506
|
+
var cur = posFromMouse(e);
|
|
507
|
+
if (cur) doSelect(cur);
|
|
279
508
|
e_preventDefault(e);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
509
|
+
focusInput();
|
|
510
|
+
updateInput = true;
|
|
511
|
+
move(); up();
|
|
512
|
+
}
|
|
513
|
+
var move = connect(document, "mousemove", operation(function(e) {
|
|
283
514
|
clearTimeout(going);
|
|
284
|
-
var cur = posFromMouse(e);
|
|
285
|
-
if (cur) setSelectionUser(start, cur);
|
|
286
515
|
e_preventDefault(e);
|
|
287
|
-
|
|
516
|
+
if (!ie && !e_button(e)) done(e);
|
|
517
|
+
else extend(e);
|
|
288
518
|
}), true);
|
|
519
|
+
var up = connect(document, "mouseup", operation(done), true);
|
|
289
520
|
}
|
|
290
|
-
function
|
|
291
|
-
var
|
|
292
|
-
|
|
293
|
-
selectWordAt(pos);
|
|
521
|
+
function onDoubleClick(e) {
|
|
522
|
+
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
523
|
+
if (n.parentNode == gutterText) return e_preventDefault(e);
|
|
294
524
|
e_preventDefault(e);
|
|
295
|
-
lastDoubleClick = +new Date;
|
|
296
525
|
}
|
|
297
526
|
function onDrop(e) {
|
|
527
|
+
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
|
298
528
|
e.preventDefault();
|
|
299
529
|
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
|
|
300
530
|
if (!pos || options.readOnly) return;
|
|
@@ -303,86 +533,148 @@ var CodeMirror = (function() {
|
|
|
303
533
|
var reader = new FileReader;
|
|
304
534
|
reader.onload = function() {
|
|
305
535
|
text[i] = reader.result;
|
|
306
|
-
if (++read == n)
|
|
536
|
+
if (++read == n) {
|
|
537
|
+
pos = clipPos(pos);
|
|
538
|
+
operation(function() {
|
|
539
|
+
var end = replaceRange(text.join(""), pos, pos);
|
|
540
|
+
setSelectionUser(pos, end);
|
|
541
|
+
})();
|
|
542
|
+
}
|
|
307
543
|
};
|
|
308
544
|
reader.readAsText(file);
|
|
309
545
|
}
|
|
310
546
|
var n = files.length, text = Array(n), read = 0;
|
|
311
547
|
for (var i = 0; i < n; ++i) loadFile(files[i], i);
|
|
312
|
-
}
|
|
313
|
-
|
|
548
|
+
} else {
|
|
549
|
+
// Don't do a replace if the drop happened inside of the selected text.
|
|
550
|
+
if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return;
|
|
314
551
|
try {
|
|
315
552
|
var text = e.dataTransfer.getData("Text");
|
|
316
|
-
if (text)
|
|
553
|
+
if (text) {
|
|
554
|
+
compoundChange(function() {
|
|
555
|
+
var curFrom = sel.from, curTo = sel.to;
|
|
556
|
+
setSelectionUser(pos, pos);
|
|
557
|
+
if (draggingText) replaceRange("", curFrom, curTo);
|
|
558
|
+
replaceSelection(text);
|
|
559
|
+
focusInput();
|
|
560
|
+
});
|
|
561
|
+
}
|
|
317
562
|
}
|
|
318
563
|
catch(e){}
|
|
319
564
|
}
|
|
320
565
|
}
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
//
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (
|
|
358
|
-
|
|
359
|
-
setSelRange(input, range.start, range.start);
|
|
566
|
+
function onDragStart(e) {
|
|
567
|
+
var txt = getSelection();
|
|
568
|
+
e.dataTransfer.setData("Text", txt);
|
|
569
|
+
|
|
570
|
+
// Use dummy image instead of default browsers image.
|
|
571
|
+
if (gecko || chrome || opera) {
|
|
572
|
+
var img = document.createElement('img');
|
|
573
|
+
img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
|
|
574
|
+
e.dataTransfer.setDragImage(img, 0, 0);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function doHandleBinding(bound, dropShift) {
|
|
579
|
+
if (typeof bound == "string") {
|
|
580
|
+
bound = commands[bound];
|
|
581
|
+
if (!bound) return false;
|
|
582
|
+
}
|
|
583
|
+
var prevShift = shiftSelecting;
|
|
584
|
+
try {
|
|
585
|
+
if (options.readOnly) suppressEdits = true;
|
|
586
|
+
if (dropShift) shiftSelecting = null;
|
|
587
|
+
bound(instance);
|
|
588
|
+
} catch(e) {
|
|
589
|
+
if (e != Pass) throw e;
|
|
590
|
+
return false;
|
|
591
|
+
} finally {
|
|
592
|
+
shiftSelecting = prevShift;
|
|
593
|
+
suppressEdits = false;
|
|
594
|
+
}
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
function handleKeyBinding(e) {
|
|
598
|
+
// Handle auto keymap transitions
|
|
599
|
+
var startMap = getKeyMap(options.keyMap), next = startMap.auto;
|
|
600
|
+
clearTimeout(maybeTransition);
|
|
601
|
+
if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
|
|
602
|
+
if (getKeyMap(options.keyMap) == startMap) {
|
|
603
|
+
options.keyMap = (next.call ? next.call(null, instance) : next);
|
|
360
604
|
}
|
|
605
|
+
}, 50);
|
|
606
|
+
|
|
607
|
+
var name = keyNames[e_prop(e, "keyCode")], handled = false;
|
|
608
|
+
if (name == null || e.altGraphKey) return false;
|
|
609
|
+
if (e_prop(e, "altKey")) name = "Alt-" + name;
|
|
610
|
+
if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
|
|
611
|
+
if (e_prop(e, "metaKey")) name = "Cmd-" + name;
|
|
612
|
+
|
|
613
|
+
var stopped = false;
|
|
614
|
+
function stop() { stopped = true; }
|
|
615
|
+
|
|
616
|
+
if (e_prop(e, "shiftKey")) {
|
|
617
|
+
handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
|
|
618
|
+
function(b) {return doHandleBinding(b, true);}, stop)
|
|
619
|
+
|| lookupKey(name, options.extraKeys, options.keyMap, function(b) {
|
|
620
|
+
if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
|
|
621
|
+
}, stop);
|
|
622
|
+
} else {
|
|
623
|
+
handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
|
|
361
624
|
}
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
-
|
|
625
|
+
if (stopped) handled = false;
|
|
626
|
+
if (handled) {
|
|
627
|
+
e_preventDefault(e);
|
|
628
|
+
restartBlink();
|
|
629
|
+
if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
|
|
630
|
+
}
|
|
631
|
+
return handled;
|
|
365
632
|
}
|
|
366
|
-
function
|
|
633
|
+
function handleCharBinding(e, ch) {
|
|
634
|
+
var handled = lookupKey("'" + ch + "'", options.extraKeys,
|
|
635
|
+
options.keyMap, function(b) { return doHandleBinding(b, true); });
|
|
636
|
+
if (handled) {
|
|
637
|
+
e_preventDefault(e);
|
|
638
|
+
restartBlink();
|
|
639
|
+
}
|
|
640
|
+
return handled;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
var lastStoppedKey = null, maybeTransition;
|
|
644
|
+
function onKeyDown(e) {
|
|
645
|
+
if (!focused) onFocus();
|
|
646
|
+
if (ie && e.keyCode == 27) { e.returnValue = false; }
|
|
647
|
+
if (pollingFast) { if (readInput()) pollingFast = false; }
|
|
367
648
|
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
649
|
+
var code = e_prop(e, "keyCode");
|
|
650
|
+
// IE does strange things with escape.
|
|
651
|
+
setShift(code == 16 || e_prop(e, "shiftKey"));
|
|
652
|
+
// First give onKeyEvent option a chance to handle this.
|
|
653
|
+
var handled = handleKeyBinding(e);
|
|
654
|
+
if (opera) {
|
|
655
|
+
lastStoppedKey = handled ? code : null;
|
|
656
|
+
// Opera has no cut event... we try to at least catch the key combo
|
|
657
|
+
if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
|
|
658
|
+
replaceSelection("");
|
|
371
659
|
}
|
|
372
|
-
if (e.keyCode == 16) shiftSelecting = null;
|
|
373
660
|
}
|
|
374
661
|
function onKeyPress(e) {
|
|
662
|
+
if (pollingFast) readInput();
|
|
375
663
|
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
376
|
-
|
|
377
|
-
|
|
664
|
+
var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
|
|
665
|
+
if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
|
|
666
|
+
if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
|
|
667
|
+
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
|
|
668
|
+
if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
|
|
378
669
|
if (mode.electricChars.indexOf(ch) > -1)
|
|
379
|
-
setTimeout(operation(function() {indentLine(sel.to.line, "smart");}),
|
|
670
|
+
setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
|
|
380
671
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
672
|
+
if (handleCharBinding(e, ch)) return;
|
|
673
|
+
fastPoll();
|
|
674
|
+
}
|
|
675
|
+
function onKeyUp(e) {
|
|
676
|
+
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
677
|
+
if (e_prop(e, "keyCode") == 16) shiftSelecting = null;
|
|
386
678
|
}
|
|
387
679
|
|
|
388
680
|
function onFocus() {
|
|
@@ -390,9 +682,9 @@ var CodeMirror = (function() {
|
|
|
390
682
|
if (!focused) {
|
|
391
683
|
if (options.onFocus) options.onFocus(instance);
|
|
392
684
|
focused = true;
|
|
393
|
-
if (
|
|
394
|
-
|
|
395
|
-
if (!leaveInputAlone)
|
|
685
|
+
if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
|
|
686
|
+
scroller.className += " CodeMirror-focused";
|
|
687
|
+
if (!leaveInputAlone) resetInput(true);
|
|
396
688
|
}
|
|
397
689
|
slowPoll();
|
|
398
690
|
restartBlink();
|
|
@@ -401,86 +693,149 @@ var CodeMirror = (function() {
|
|
|
401
693
|
if (focused) {
|
|
402
694
|
if (options.onBlur) options.onBlur(instance);
|
|
403
695
|
focused = false;
|
|
404
|
-
|
|
696
|
+
if (bracketHighlighted)
|
|
697
|
+
operation(function(){
|
|
698
|
+
if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
|
|
699
|
+
})();
|
|
700
|
+
scroller.className = scroller.className.replace(" CodeMirror-focused", "");
|
|
405
701
|
}
|
|
406
702
|
clearInterval(blinker);
|
|
407
703
|
setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
|
|
408
704
|
}
|
|
409
705
|
|
|
706
|
+
function chopDelta(delta) {
|
|
707
|
+
// Make sure we always scroll a little bit for any nonzero delta.
|
|
708
|
+
if (delta > 0.0 && delta < 1.0) return 1;
|
|
709
|
+
else if (delta > -1.0 && delta < 0.0) return -1;
|
|
710
|
+
else return Math.round(delta);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function onMouseWheel(e) {
|
|
714
|
+
var deltaX = 0, deltaY = 0;
|
|
715
|
+
if (e.type == "DOMMouseScroll") { // Firefox
|
|
716
|
+
var delta = -e.detail * 8.0;
|
|
717
|
+
if (e.axis == e.HORIZONTAL_AXIS) deltaX = delta;
|
|
718
|
+
else if (e.axis == e.VERTICAL_AXIS) deltaY = delta;
|
|
719
|
+
} else if (e.wheelDeltaX !== undefined && e.wheelDeltaY !== undefined) { // WebKit
|
|
720
|
+
deltaX = e.wheelDeltaX / 3.0;
|
|
721
|
+
deltaY = e.wheelDeltaY / 3.0;
|
|
722
|
+
} else if (e.wheelDelta !== undefined) { // IE or Opera
|
|
723
|
+
deltaY = e.wheelDelta / 3.0;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
var scrolled = false;
|
|
727
|
+
deltaX = chopDelta(deltaX);
|
|
728
|
+
deltaY = chopDelta(deltaY);
|
|
729
|
+
if ((deltaX > 0 && scroller.scrollLeft > 0) ||
|
|
730
|
+
(deltaX < 0 && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth)) {
|
|
731
|
+
scroller.scrollLeft -= deltaX;
|
|
732
|
+
scrolled = true;
|
|
733
|
+
}
|
|
734
|
+
if ((deltaY > 0 && scrollbar.scrollTop > 0) ||
|
|
735
|
+
(deltaY < 0 && scrollbar.scrollTop + scrollbar.clientHeight < scrollbar.scrollHeight)) {
|
|
736
|
+
scrollbar.scrollTop -= deltaY;
|
|
737
|
+
scrolled = true;
|
|
738
|
+
}
|
|
739
|
+
if (scrolled) e_stop(e);
|
|
740
|
+
}
|
|
741
|
+
|
|
410
742
|
// Replace the range from from to to by the strings in newText.
|
|
411
743
|
// Afterwards, set the selection to selFrom, selTo.
|
|
412
744
|
function updateLines(from, to, newText, selFrom, selTo) {
|
|
745
|
+
if (suppressEdits) return;
|
|
413
746
|
if (history) {
|
|
414
747
|
var old = [];
|
|
415
|
-
|
|
748
|
+
doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });
|
|
416
749
|
history.addChange(from.line, newText.length, old);
|
|
417
750
|
while (history.done.length > options.undoDepth) history.done.shift();
|
|
418
751
|
}
|
|
419
752
|
updateLinesNoUndo(from, to, newText, selFrom, selTo);
|
|
420
753
|
}
|
|
421
754
|
function unredoHelper(from, to) {
|
|
422
|
-
|
|
423
|
-
|
|
755
|
+
if (!from.length) return;
|
|
756
|
+
var set = from.pop(), out = [];
|
|
757
|
+
for (var i = set.length - 1; i >= 0; i -= 1) {
|
|
758
|
+
var change = set[i];
|
|
424
759
|
var replaced = [], end = change.start + change.added;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
var pos =
|
|
428
|
-
|
|
429
|
-
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch:
|
|
430
|
-
updateInput = true;
|
|
760
|
+
doc.iter(change.start, end, function(line) { replaced.push(line.text); });
|
|
761
|
+
out.push({start: change.start, added: change.old.length, old: replaced});
|
|
762
|
+
var pos = {line: change.start + change.old.length - 1,
|
|
763
|
+
ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])};
|
|
764
|
+
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
|
|
431
765
|
}
|
|
766
|
+
updateInput = true;
|
|
767
|
+
to.push(out);
|
|
432
768
|
}
|
|
433
769
|
function undo() {unredoHelper(history.done, history.undone);}
|
|
434
770
|
function redo() {unredoHelper(history.undone, history.done);}
|
|
435
771
|
|
|
436
772
|
function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
|
|
773
|
+
if (suppressEdits) return;
|
|
437
774
|
var recomputeMaxLength = false, maxLineLength = maxLine.length;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
775
|
+
if (!options.lineWrapping)
|
|
776
|
+
doc.iter(from.line, to.line + 1, function(line) {
|
|
777
|
+
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
|
778
|
+
});
|
|
779
|
+
if (from.line != to.line || newText.length > 1) gutterDirty = true;
|
|
441
780
|
|
|
442
|
-
var nlines = to.line - from.line, firstLine =
|
|
781
|
+
var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);
|
|
443
782
|
// First adjust the line structure, taking some care to leave highlighting intact.
|
|
444
|
-
if (
|
|
783
|
+
if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == "") {
|
|
784
|
+
// This is a whole-line replace. Treated specially to make
|
|
785
|
+
// sure line objects move the way they are supposed to.
|
|
786
|
+
var added = [], prevLine = null;
|
|
787
|
+
if (from.line) {
|
|
788
|
+
prevLine = getLine(from.line - 1);
|
|
789
|
+
prevLine.fixMarkEnds(lastLine);
|
|
790
|
+
} else lastLine.fixMarkStarts();
|
|
791
|
+
for (var i = 0, e = newText.length - 1; i < e; ++i)
|
|
792
|
+
added.push(Line.inheritMarks(newText[i], prevLine));
|
|
793
|
+
if (nlines) doc.remove(from.line, nlines, callbacks);
|
|
794
|
+
if (added.length) doc.insert(from.line, added);
|
|
795
|
+
} else if (firstLine == lastLine) {
|
|
445
796
|
if (newText.length == 1)
|
|
446
797
|
firstLine.replace(from.ch, to.ch, newText[0]);
|
|
447
798
|
else {
|
|
448
799
|
lastLine = firstLine.split(to.ch, newText[newText.length-1]);
|
|
449
|
-
|
|
450
|
-
firstLine.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
800
|
+
firstLine.replace(from.ch, null, newText[0]);
|
|
801
|
+
firstLine.fixMarkEnds(lastLine);
|
|
802
|
+
var added = [];
|
|
803
|
+
for (var i = 1, e = newText.length - 1; i < e; ++i)
|
|
804
|
+
added.push(Line.inheritMarks(newText[i], firstLine));
|
|
805
|
+
added.push(lastLine);
|
|
806
|
+
doc.insert(from.line + 1, added);
|
|
454
807
|
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
else {
|
|
461
|
-
var
|
|
462
|
-
firstLine.replace(from.ch,
|
|
463
|
-
lastLine.replace(
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
var l =
|
|
480
|
-
if (l.length > maxLineLength) {
|
|
481
|
-
maxLineLength = l.length;
|
|
808
|
+
} else if (newText.length == 1) {
|
|
809
|
+
firstLine.replace(from.ch, null, newText[0]);
|
|
810
|
+
lastLine.replace(null, to.ch, "");
|
|
811
|
+
firstLine.append(lastLine);
|
|
812
|
+
doc.remove(from.line + 1, nlines, callbacks);
|
|
813
|
+
} else {
|
|
814
|
+
var added = [];
|
|
815
|
+
firstLine.replace(from.ch, null, newText[0]);
|
|
816
|
+
lastLine.replace(null, to.ch, newText[newText.length-1]);
|
|
817
|
+
firstLine.fixMarkEnds(lastLine);
|
|
818
|
+
for (var i = 1, e = newText.length - 1; i < e; ++i)
|
|
819
|
+
added.push(Line.inheritMarks(newText[i], firstLine));
|
|
820
|
+
if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);
|
|
821
|
+
doc.insert(from.line + 1, added);
|
|
822
|
+
}
|
|
823
|
+
if (options.lineWrapping) {
|
|
824
|
+
var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
|
|
825
|
+
doc.iter(from.line, from.line + newText.length, function(line) {
|
|
826
|
+
if (line.hidden) return;
|
|
827
|
+
var guess = Math.ceil(line.text.length / perLine) || 1;
|
|
828
|
+
if (guess != line.height) updateLineHeight(line, guess);
|
|
829
|
+
});
|
|
830
|
+
} else {
|
|
831
|
+
doc.iter(from.line, from.line + newText.length, function(line) {
|
|
832
|
+
var l = line.text;
|
|
833
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
834
|
+
maxLine = l; maxLineLength = l.length; maxLineChanged = true;
|
|
835
|
+
recomputeMaxLength = false;
|
|
482
836
|
}
|
|
483
|
-
}
|
|
837
|
+
});
|
|
838
|
+
if (recomputeMaxLength) updateMaxLine = true;
|
|
484
839
|
}
|
|
485
840
|
|
|
486
841
|
// Add these lines to the work array, so that they will be
|
|
@@ -491,24 +846,70 @@ var CodeMirror = (function() {
|
|
|
491
846
|
if (task < from.line) newWork.push(task);
|
|
492
847
|
else if (task > to.line) newWork.push(task + lendiff);
|
|
493
848
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
} else {
|
|
498
|
-
newWork.push(from.line);
|
|
499
|
-
}
|
|
849
|
+
var hlEnd = from.line + Math.min(newText.length, 500);
|
|
850
|
+
highlightLines(from.line, hlEnd);
|
|
851
|
+
newWork.push(hlEnd);
|
|
500
852
|
work = newWork;
|
|
501
853
|
startWorker(100);
|
|
502
854
|
// Remember that these lines changed, for updating the display
|
|
503
855
|
changes.push({from: from.line, to: to.line + 1, diff: lendiff});
|
|
504
|
-
|
|
856
|
+
var changeObj = {from: from, to: to, text: newText};
|
|
857
|
+
if (textChanged) {
|
|
858
|
+
for (var cur = textChanged; cur.next; cur = cur.next) {}
|
|
859
|
+
cur.next = changeObj;
|
|
860
|
+
} else textChanged = changeObj;
|
|
505
861
|
|
|
506
862
|
// Update the selection
|
|
507
863
|
function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
|
|
508
|
-
setSelection(selFrom, selTo
|
|
864
|
+
setSelection(clipPos(selFrom), clipPos(selTo),
|
|
865
|
+
updateLine(sel.from.line), updateLine(sel.to.line));
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
function needsScrollbar() {
|
|
869
|
+
var realHeight = doc.height * textHeight() + 2 * paddingTop();
|
|
870
|
+
return realHeight - 1 > scroller.offsetHeight ? realHeight : false;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
function updateVerticalScroll(scrollTop) {
|
|
874
|
+
var scrollHeight = needsScrollbar();
|
|
875
|
+
scrollbar.style.display = scrollHeight ? "block" : "none";
|
|
876
|
+
if (scrollHeight) {
|
|
877
|
+
scrollbarInner.style.height = scrollHeight + "px";
|
|
878
|
+
scrollbar.style.height = scroller.offsetHeight + "px";
|
|
879
|
+
if (scrollTop != null) scrollbar.scrollTop = scrollTop;
|
|
880
|
+
}
|
|
881
|
+
// Position the mover div to align with the current virtual scroll position
|
|
882
|
+
mover.style.top = (displayOffset * textHeight() - scrollbar.scrollTop) + "px";
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// On Mac OS X Lion and up, detect whether the mouse is plugged in by measuring
|
|
886
|
+
// the width of a div with a scrollbar in it. If the width is <= 1, then
|
|
887
|
+
// the mouse isn't plugged in and scrollbars should overlap the content.
|
|
888
|
+
function overlapScrollbars() {
|
|
889
|
+
var tmpSb = document.createElement('div'),
|
|
890
|
+
tmpSbInner = document.createElement('div');
|
|
891
|
+
tmpSb.className = "CodeMirror-scrollbar";
|
|
892
|
+
tmpSb.style.cssText = "position: absolute; left: -9999px; height: 100px;";
|
|
893
|
+
tmpSbInner.className = "CodeMirror-scrollbar-inner";
|
|
894
|
+
tmpSbInner.style.height = "200px";
|
|
895
|
+
tmpSb.appendChild(tmpSbInner);
|
|
896
|
+
|
|
897
|
+
document.body.appendChild(tmpSb);
|
|
898
|
+
var result = (tmpSb.offsetWidth <= 1);
|
|
899
|
+
document.body.removeChild(tmpSb);
|
|
900
|
+
return result;
|
|
901
|
+
}
|
|
509
902
|
|
|
510
|
-
|
|
511
|
-
|
|
903
|
+
function computeMaxLength() {
|
|
904
|
+
var maxLineLength = 0;
|
|
905
|
+
maxLine = ""; maxLineChanged = true;
|
|
906
|
+
doc.iter(0, doc.size, function(line) {
|
|
907
|
+
var l = line.text;
|
|
908
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
909
|
+
maxLineLength = l.length; maxLine = l;
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
updateMaxLine = false;
|
|
512
913
|
}
|
|
513
914
|
|
|
514
915
|
function replaceRange(code, from, to) {
|
|
@@ -544,193 +945,233 @@ var CodeMirror = (function() {
|
|
|
544
945
|
updateLines(from, to, code, newSel.from, newSel.to);
|
|
545
946
|
}
|
|
546
947
|
|
|
547
|
-
function getRange(from, to) {
|
|
948
|
+
function getRange(from, to, lineSep) {
|
|
548
949
|
var l1 = from.line, l2 = to.line;
|
|
549
|
-
if (l1 == l2) return
|
|
550
|
-
var code = [
|
|
551
|
-
|
|
552
|
-
code.push(
|
|
553
|
-
return code.join("\n");
|
|
950
|
+
if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
|
|
951
|
+
var code = [getLine(l1).text.slice(from.ch)];
|
|
952
|
+
doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
|
|
953
|
+
code.push(getLine(l2).text.slice(0, to.ch));
|
|
954
|
+
return code.join(lineSep || "\n");
|
|
554
955
|
}
|
|
555
|
-
function getSelection() {
|
|
556
|
-
return getRange(sel.from, sel.to);
|
|
956
|
+
function getSelection(lineSep) {
|
|
957
|
+
return getRange(sel.from, sel.to, lineSep);
|
|
557
958
|
}
|
|
558
959
|
|
|
559
960
|
var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
|
|
560
961
|
function slowPoll() {
|
|
561
962
|
if (pollingFast) return;
|
|
562
|
-
poll.set(
|
|
963
|
+
poll.set(options.pollInterval, function() {
|
|
563
964
|
startOperation();
|
|
564
965
|
readInput();
|
|
565
966
|
if (focused) slowPoll();
|
|
566
967
|
endOperation();
|
|
567
968
|
});
|
|
568
969
|
}
|
|
569
|
-
function fastPoll(
|
|
970
|
+
function fastPoll() {
|
|
570
971
|
var missed = false;
|
|
571
972
|
pollingFast = true;
|
|
572
973
|
function p() {
|
|
573
974
|
startOperation();
|
|
574
975
|
var changed = readInput();
|
|
575
|
-
if (changed &&
|
|
576
|
-
if (changed == "moved" && movementKeys[keyId] == null) movementKeys[keyId] = true;
|
|
577
|
-
if (changed == "changed") movementKeys[keyId] = false;
|
|
578
|
-
}
|
|
579
|
-
if (!changed && !missed) {missed = true; poll.set(80, p);}
|
|
976
|
+
if (!changed && !missed) {missed = true; poll.set(60, p);}
|
|
580
977
|
else {pollingFast = false; slowPoll();}
|
|
581
978
|
endOperation();
|
|
582
979
|
}
|
|
583
980
|
poll.set(20, p);
|
|
584
981
|
}
|
|
585
982
|
|
|
586
|
-
//
|
|
587
|
-
//
|
|
588
|
-
//
|
|
983
|
+
// Previnput is a hack to work with IME. If we reset the textarea
|
|
984
|
+
// on every change, that breaks IME. So we look for changes
|
|
985
|
+
// compared to the previous content instead. (Modern browsers have
|
|
986
|
+
// events that indicate IME taking place, but these are not widely
|
|
987
|
+
// supported or compatible enough yet to rely on.)
|
|
988
|
+
var prevInput = "";
|
|
589
989
|
function readInput() {
|
|
590
|
-
if (leaveInputAlone || !focused) return;
|
|
591
|
-
var
|
|
592
|
-
if (
|
|
593
|
-
|
|
594
|
-
var
|
|
595
|
-
|
|
596
|
-
if (
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
for (;;) {
|
|
605
|
-
var found = text.indexOf("\n", pos);
|
|
606
|
-
if (found == -1 || (text.charAt(found-1) == "\r" ? found - 1 : found) >= n)
|
|
607
|
-
return {line: startLine, ch: n - pos};
|
|
608
|
-
++startLine;
|
|
609
|
-
pos = found + 1;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
var from = computeOffset(sr.start, editing.from),
|
|
613
|
-
to = computeOffset(sr.end, editing.from);
|
|
614
|
-
// Here we have to take the reducedSelection hack into account,
|
|
615
|
-
// so that you can, for example, press shift-up at the start of
|
|
616
|
-
// your selection and have the right thing happen.
|
|
617
|
-
if (rs) {
|
|
618
|
-
var head = sr.start == rs.anchor ? to : from;
|
|
619
|
-
var tail = shiftSelecting ? sel.to : sr.start == rs.anchor ? from : to;
|
|
620
|
-
if (sel.inverted = posLess(head, tail)) { from = head; to = tail; }
|
|
621
|
-
else { reducedSelection = null; from = tail; to = head; }
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// In some cases (cursor on same line as before), we don't have
|
|
625
|
-
// to update the textarea content at all.
|
|
626
|
-
if (from.line == to.line && from.line == sel.from.line && from.line == sel.to.line && !shiftSelecting)
|
|
627
|
-
updateInput = false;
|
|
628
|
-
|
|
629
|
-
// Magic mess to extract precise edited range from the changed
|
|
630
|
-
// string.
|
|
631
|
-
if (changed) {
|
|
632
|
-
var start = 0, end = text.length, len = Math.min(end, editing.text.length);
|
|
633
|
-
var c, line = editing.from, nl = -1;
|
|
634
|
-
while (start < len && (c = text.charAt(start)) == editing.text.charAt(start)) {
|
|
635
|
-
++start;
|
|
636
|
-
if (c == "\n") {line++; nl = start;}
|
|
637
|
-
}
|
|
638
|
-
var ch = nl > -1 ? start - nl : start, endline = editing.to - 1, edend = editing.text.length;
|
|
639
|
-
for (;;) {
|
|
640
|
-
c = editing.text.charAt(edend);
|
|
641
|
-
if (text.charAt(end) != c) {++end; ++edend; break;}
|
|
642
|
-
if (c == "\n") endline--;
|
|
643
|
-
if (edend <= start || end <= start) break;
|
|
644
|
-
--end; --edend;
|
|
645
|
-
}
|
|
646
|
-
var nl = editing.text.lastIndexOf("\n", edend - 1), endch = nl == -1 ? edend : edend - nl - 1;
|
|
647
|
-
updateLines({line: line, ch: ch}, {line: endline, ch: endch}, splitLines(text.slice(start, end)), from, to);
|
|
648
|
-
if (line != endline || from.line != line) updateInput = true;
|
|
649
|
-
}
|
|
650
|
-
else setSelection(from, to);
|
|
651
|
-
|
|
652
|
-
editing.text = text; editing.start = sr.start; editing.end = sr.end;
|
|
653
|
-
return changed ? "changed" : moved ? "moved" : false;
|
|
990
|
+
if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false;
|
|
991
|
+
var text = input.value;
|
|
992
|
+
if (text == prevInput) return false;
|
|
993
|
+
shiftSelecting = null;
|
|
994
|
+
var same = 0, l = Math.min(prevInput.length, text.length);
|
|
995
|
+
while (same < l && prevInput[same] == text[same]) ++same;
|
|
996
|
+
if (same < prevInput.length)
|
|
997
|
+
sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};
|
|
998
|
+
else if (overwrite && posEq(sel.from, sel.to))
|
|
999
|
+
sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
|
|
1000
|
+
replaceSelection(text.slice(same), "end");
|
|
1001
|
+
if (text.length > 1000) { input.value = prevInput = ""; }
|
|
1002
|
+
else prevInput = text;
|
|
1003
|
+
return true;
|
|
654
1004
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
for (var i = from; i < to; ++i) text.push(lines[i].text);
|
|
662
|
-
text = input.value = text.join(lineSep);
|
|
663
|
-
var startch = sel.from.ch, endch = sel.to.ch;
|
|
664
|
-
for (var i = from; i < sel.from.line; ++i)
|
|
665
|
-
startch += lineSep.length + lines[i].text.length;
|
|
666
|
-
for (var i = from; i < sel.to.line; ++i)
|
|
667
|
-
endch += lineSep.length + lines[i].text.length;
|
|
668
|
-
editing = {text: text, from: from, to: to, start: startch, end: endch};
|
|
669
|
-
setSelRange(input, startch, reducedSelection ? startch : endch);
|
|
1005
|
+
function resetInput(user) {
|
|
1006
|
+
if (!posEq(sel.from, sel.to)) {
|
|
1007
|
+
prevInput = "";
|
|
1008
|
+
input.value = getSelection();
|
|
1009
|
+
selectInput(input);
|
|
1010
|
+
} else if (user) prevInput = input.value = "";
|
|
670
1011
|
}
|
|
1012
|
+
|
|
671
1013
|
function focusInput() {
|
|
672
1014
|
if (options.readOnly != "nocursor") input.focus();
|
|
673
1015
|
}
|
|
674
1016
|
|
|
675
1017
|
function scrollEditorIntoView() {
|
|
676
|
-
if (!cursor.getBoundingClientRect) return;
|
|
677
1018
|
var rect = cursor.getBoundingClientRect();
|
|
678
|
-
|
|
679
|
-
if (rect.top
|
|
1019
|
+
// IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
|
|
1020
|
+
if (ie && rect.top == rect.bottom) return;
|
|
1021
|
+
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
|
1022
|
+
if (rect.top < 0 || rect.bottom > winH) scrollCursorIntoView();
|
|
680
1023
|
}
|
|
681
1024
|
function scrollCursorIntoView() {
|
|
1025
|
+
var coords = calculateCursorCoords();
|
|
1026
|
+
return scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
|
|
1027
|
+
}
|
|
1028
|
+
function calculateCursorCoords() {
|
|
682
1029
|
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
|
|
683
|
-
|
|
1030
|
+
var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
|
|
1031
|
+
return {x: x, y: cursor.y, yBot: cursor.yBot};
|
|
684
1032
|
}
|
|
685
1033
|
function scrollIntoView(x1, y1, x2, y2) {
|
|
686
|
-
var
|
|
1034
|
+
var scrollPos = calculateScrollPos(x1, y1, x2, y2), scrolled = false;
|
|
1035
|
+
if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft; scrolled = true;}
|
|
1036
|
+
if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scrollPos.scrollTop; scrolled = true;}
|
|
1037
|
+
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
1038
|
+
}
|
|
1039
|
+
function calculateScrollPos(x1, y1, x2, y2) {
|
|
1040
|
+
var pl = paddingLeft(), pt = paddingTop();
|
|
687
1041
|
y1 += pt; y2 += pt; x1 += pl; x2 += pl;
|
|
688
|
-
var screen = scroller.clientHeight, screentop =
|
|
689
|
-
|
|
690
|
-
|
|
1042
|
+
var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
|
|
1043
|
+
var docBottom = scroller.scrollHeight;
|
|
1044
|
+
var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;;
|
|
1045
|
+
if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
|
|
1046
|
+
else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
|
|
691
1047
|
|
|
692
1048
|
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
1049
|
+
var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
|
|
1050
|
+
var atLeft = x1 < gutterw + pl + 10;
|
|
1051
|
+
if (x1 < screenleft + gutterw || atLeft) {
|
|
1052
|
+
if (atLeft) x1 = 0;
|
|
1053
|
+
result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
|
|
1054
|
+
} else if (x2 > screenw + screenleft - 3) {
|
|
1055
|
+
result.scrollLeft = x2 + 10 - screenw;
|
|
697
1056
|
}
|
|
698
|
-
else if (x2 > screenw + screenleft) {
|
|
699
|
-
scroller.scrollLeft = x2 + 10 - screenw;
|
|
700
|
-
scrolled = true;
|
|
701
|
-
if (x2 > code.clientWidth) result = false;
|
|
702
|
-
}
|
|
703
|
-
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
704
1057
|
return result;
|
|
705
1058
|
}
|
|
706
1059
|
|
|
707
|
-
function visibleLines() {
|
|
708
|
-
var lh =
|
|
709
|
-
|
|
710
|
-
|
|
1060
|
+
function visibleLines(scrollTop) {
|
|
1061
|
+
var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop();
|
|
1062
|
+
var fromHeight = Math.max(0, Math.floor(top / lh));
|
|
1063
|
+
var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
|
|
1064
|
+
return {from: lineAtHeight(doc, fromHeight),
|
|
1065
|
+
to: lineAtHeight(doc, toHeight)};
|
|
711
1066
|
}
|
|
712
1067
|
// Uses a set of changes plus the current scroll position to
|
|
713
1068
|
// determine which DOM updates have to be made, and makes the
|
|
714
1069
|
// updates.
|
|
715
|
-
function updateDisplay(changes) {
|
|
1070
|
+
function updateDisplay(changes, suppressCallback, scrollTop) {
|
|
716
1071
|
if (!scroller.clientWidth) {
|
|
717
|
-
showingFrom = showingTo = 0;
|
|
1072
|
+
showingFrom = showingTo = displayOffset = 0;
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
// Compute the new visible window
|
|
1076
|
+
// If scrollTop is specified, use that to determine which lines
|
|
1077
|
+
// to render instead of the current scrollbar position.
|
|
1078
|
+
var visible = visibleLines(scrollTop);
|
|
1079
|
+
// Bail out if the visible area is already rendered and nothing changed.
|
|
1080
|
+
if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) {
|
|
1081
|
+
updateVerticalScroll(scrollTop);
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
|
|
1085
|
+
if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
|
|
1086
|
+
if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
|
|
1087
|
+
|
|
1088
|
+
// Create a range of theoretically intact lines, and punch holes
|
|
1089
|
+
// in that using the change info.
|
|
1090
|
+
var intact = changes === true ? [] :
|
|
1091
|
+
computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);
|
|
1092
|
+
// Clip off the parts that won't be visible
|
|
1093
|
+
var intactLines = 0;
|
|
1094
|
+
for (var i = 0; i < intact.length; ++i) {
|
|
1095
|
+
var range = intact[i];
|
|
1096
|
+
if (range.from < from) {range.domStart += (from - range.from); range.from = from;}
|
|
1097
|
+
if (range.to > to) range.to = to;
|
|
1098
|
+
if (range.from >= range.to) intact.splice(i--, 1);
|
|
1099
|
+
else intactLines += range.to - range.from;
|
|
1100
|
+
}
|
|
1101
|
+
if (intactLines == to - from && from == showingFrom && to == showingTo) {
|
|
1102
|
+
updateVerticalScroll(scrollTop);
|
|
718
1103
|
return;
|
|
719
1104
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
var
|
|
1105
|
+
intact.sort(function(a, b) {return a.domStart - b.domStart;});
|
|
1106
|
+
|
|
1107
|
+
var th = textHeight(), gutterDisplay = gutter.style.display;
|
|
1108
|
+
lineDiv.style.display = "none";
|
|
1109
|
+
patchDisplay(from, to, intact);
|
|
1110
|
+
lineDiv.style.display = gutter.style.display = "";
|
|
1111
|
+
|
|
1112
|
+
var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
|
|
1113
|
+
// This is just a bogus formula that detects when the editor is
|
|
1114
|
+
// resized or the font size changes.
|
|
1115
|
+
if (different) lastSizeC = scroller.clientHeight + th;
|
|
1116
|
+
showingFrom = from; showingTo = to;
|
|
1117
|
+
displayOffset = heightAtLine(doc, from);
|
|
1118
|
+
|
|
1119
|
+
// Since this is all rather error prone, it is honoured with the
|
|
1120
|
+
// only assertion in the whole file.
|
|
1121
|
+
if (lineDiv.childNodes.length != showingTo - showingFrom)
|
|
1122
|
+
throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
|
|
1123
|
+
" nodes=" + lineDiv.childNodes.length);
|
|
1124
|
+
|
|
1125
|
+
function checkHeights() {
|
|
1126
|
+
var curNode = lineDiv.firstChild, heightChanged = false;
|
|
1127
|
+
doc.iter(showingFrom, showingTo, function(line) {
|
|
1128
|
+
if (!line.hidden) {
|
|
1129
|
+
var height = Math.round(curNode.offsetHeight / th) || 1;
|
|
1130
|
+
if (line.height != height) {
|
|
1131
|
+
updateLineHeight(line, height);
|
|
1132
|
+
gutterDirty = heightChanged = true;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
curNode = curNode.nextSibling;
|
|
1136
|
+
});
|
|
1137
|
+
return heightChanged;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
if (options.lineWrapping) {
|
|
1141
|
+
checkHeights();
|
|
1142
|
+
var scrollHeight = needsScrollbar();
|
|
1143
|
+
var shouldHaveScrollbar = scrollHeight ? "block" : "none";
|
|
1144
|
+
if (scrollbar.style.display != shouldHaveScrollbar) {
|
|
1145
|
+
scrollbar.style.display = shouldHaveScrollbar;
|
|
1146
|
+
if (scrollHeight) scrollbarInner.style.height = scrollHeight + "px";
|
|
1147
|
+
checkHeights();
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
gutter.style.display = gutterDisplay;
|
|
1152
|
+
if (different || gutterDirty) {
|
|
1153
|
+
// If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
|
|
1154
|
+
updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
|
|
1155
|
+
}
|
|
1156
|
+
updateVerticalScroll(scrollTop);
|
|
1157
|
+
updateSelection();
|
|
1158
|
+
if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
|
|
1159
|
+
return true;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
function computeIntact(intact, changes) {
|
|
723
1163
|
for (var i = 0, l = changes.length || 0; i < l; ++i) {
|
|
724
1164
|
var change = changes[i], intact2 = [], diff = change.diff || 0;
|
|
725
1165
|
for (var j = 0, l2 = intact.length; j < l2; ++j) {
|
|
726
1166
|
var range = intact[j];
|
|
727
|
-
if (change.to <= range.from)
|
|
728
|
-
intact2.push({from: range.from + diff, to: range.to + diff,
|
|
729
|
-
|
|
1167
|
+
if (change.to <= range.from && change.diff)
|
|
1168
|
+
intact2.push({from: range.from + diff, to: range.to + diff,
|
|
1169
|
+
domStart: range.domStart});
|
|
1170
|
+
else if (change.to <= range.from || change.from >= range.to)
|
|
730
1171
|
intact2.push(range);
|
|
731
1172
|
else {
|
|
732
1173
|
if (change.from > range.from)
|
|
733
|
-
intact2.push({from: range.from, to: change.from, domStart: range.domStart})
|
|
1174
|
+
intact2.push({from: range.from, to: change.from, domStart: range.domStart});
|
|
734
1175
|
if (change.to < range.to)
|
|
735
1176
|
intact2.push({from: change.to + diff, to: range.to + diff,
|
|
736
1177
|
domStart: range.domStart + (change.to - range.from)});
|
|
@@ -738,165 +1179,130 @@ var CodeMirror = (function() {
|
|
|
738
1179
|
}
|
|
739
1180
|
intact = intact2;
|
|
740
1181
|
}
|
|
741
|
-
|
|
742
|
-
// Then, determine which lines we'd want to see, and which
|
|
743
|
-
// updates have to be made to get there.
|
|
744
|
-
var visible = visibleLines();
|
|
745
|
-
var from = Math.min(showingFrom, Math.max(visible.from - 3, 0)),
|
|
746
|
-
to = Math.min(lines.length, Math.max(showingTo, visible.to + 3)),
|
|
747
|
-
updates = [], domPos = 0, domEnd = showingTo - showingFrom, pos = from, changedLines = 0;
|
|
748
|
-
|
|
749
|
-
for (var i = 0, l = intact.length; i < l; ++i) {
|
|
750
|
-
var range = intact[i];
|
|
751
|
-
if (range.to <= from) continue;
|
|
752
|
-
if (range.from >= to) break;
|
|
753
|
-
if (range.domStart > domPos || range.from > pos) {
|
|
754
|
-
updates.push({from: pos, to: range.from, domSize: range.domStart - domPos, domStart: domPos});
|
|
755
|
-
changedLines += range.from - pos;
|
|
756
|
-
}
|
|
757
|
-
pos = range.to;
|
|
758
|
-
domPos = range.domStart + (range.to - range.from);
|
|
759
|
-
}
|
|
760
|
-
if (domPos != domEnd || pos != to) {
|
|
761
|
-
changedLines += Math.abs(to - pos);
|
|
762
|
-
updates.push({from: pos, to: to, domSize: domEnd - domPos, domStart: domPos});
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
if (!updates.length) return;
|
|
766
|
-
lineDiv.style.display = "none";
|
|
767
|
-
// If more than 30% of the screen needs update, just do a full
|
|
768
|
-
// redraw (which is quicker than patching)
|
|
769
|
-
if (changedLines > (visible.to - visible.from) * .3)
|
|
770
|
-
refreshDisplay(from = Math.max(visible.from - 10, 0), to = Math.min(visible.to + 7, lines.length));
|
|
771
|
-
// Otherwise, only update the stuff that needs updating.
|
|
772
|
-
else
|
|
773
|
-
patchDisplay(updates);
|
|
774
|
-
lineDiv.style.display = "";
|
|
775
|
-
|
|
776
|
-
// Position the mover div to align with the lines it's supposed
|
|
777
|
-
// to be showing (which will cover the visible display)
|
|
778
|
-
var different = from != showingFrom || to != showingTo || lastHeight != scroller.clientHeight;
|
|
779
|
-
showingFrom = from; showingTo = to;
|
|
780
|
-
mover.style.top = (from * lineHeight()) + "px";
|
|
781
|
-
if (different) {
|
|
782
|
-
lastHeight = scroller.clientHeight;
|
|
783
|
-
code.style.height = (lines.length * lineHeight() + 2 * paddingTop()) + "px";
|
|
784
|
-
}
|
|
785
|
-
if (different || updates.length) updateGutter();
|
|
786
|
-
|
|
787
|
-
if (maxWidth == null) maxWidth = stringWidth(maxLine);
|
|
788
|
-
if (maxWidth > scroller.clientWidth) {
|
|
789
|
-
lineSpace.style.width = maxWidth + "px";
|
|
790
|
-
// Needed to prevent odd wrapping/hiding of widgets placed in here.
|
|
791
|
-
code.style.width = "";
|
|
792
|
-
code.style.width = scroller.scrollWidth + "px";
|
|
793
|
-
} else {
|
|
794
|
-
lineSpace.style.width = code.style.width = "";
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
// Since this is all rather error prone, it is honoured with the
|
|
798
|
-
// only assertion in the whole file.
|
|
799
|
-
if (lineDiv.childNodes.length != showingTo - showingFrom)
|
|
800
|
-
throw new Error("BAD PATCH! " + JSON.stringify(updates) + " size=" + (showingTo - showingFrom) +
|
|
801
|
-
" nodes=" + lineDiv.childNodes.length);
|
|
802
|
-
updateCursor();
|
|
1182
|
+
return intact;
|
|
803
1183
|
}
|
|
804
1184
|
|
|
805
|
-
function
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
else if (sel.from.line == i) {
|
|
814
|
-
if (sel.to.line == i) {ch1 = sel.from.ch; ch2 = sel.to.ch;}
|
|
815
|
-
else {inSel = true; ch1 = sel.from.ch;}
|
|
1185
|
+
function patchDisplay(from, to, intact) {
|
|
1186
|
+
// The first pass removes the DOM nodes that aren't intact.
|
|
1187
|
+
if (!intact.length) lineDiv.innerHTML = "";
|
|
1188
|
+
else {
|
|
1189
|
+
function killNode(node) {
|
|
1190
|
+
var tmp = node.nextSibling;
|
|
1191
|
+
node.parentNode.removeChild(node);
|
|
1192
|
+
return tmp;
|
|
816
1193
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
// Slightly different algorithm for IE (badInnerHTML), since
|
|
823
|
-
// there .innerHTML on PRE nodes is dumb, and discards
|
|
824
|
-
// whitespace.
|
|
825
|
-
var sfrom = sel.from.line, sto = sel.to.line, off = 0,
|
|
826
|
-
scratch = badInnerHTML && targetDocument.createElement("div");
|
|
827
|
-
for (var i = 0, e = updates.length; i < e; ++i) {
|
|
828
|
-
var rec = updates[i];
|
|
829
|
-
var extra = (rec.to - rec.from) - rec.domSize;
|
|
830
|
-
var nodeAfter = lineDiv.childNodes[rec.domStart + rec.domSize + off] || null;
|
|
831
|
-
if (badInnerHTML)
|
|
832
|
-
for (var j = Math.max(-extra, rec.domSize); j > 0; --j)
|
|
833
|
-
lineDiv.removeChild(nodeAfter ? nodeAfter.previousSibling : lineDiv.lastChild);
|
|
834
|
-
else if (extra) {
|
|
835
|
-
for (var j = Math.max(0, extra); j > 0; --j)
|
|
836
|
-
lineDiv.insertBefore(targetDocument.createElement("pre"), nodeAfter);
|
|
837
|
-
for (var j = Math.max(0, -extra); j > 0; --j)
|
|
838
|
-
lineDiv.removeChild(nodeAfter ? nodeAfter.previousSibling : lineDiv.lastChild);
|
|
1194
|
+
var domPos = 0, curNode = lineDiv.firstChild, n;
|
|
1195
|
+
for (var i = 0; i < intact.length; ++i) {
|
|
1196
|
+
var cur = intact[i];
|
|
1197
|
+
while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}
|
|
1198
|
+
for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}
|
|
839
1199
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
else {inSel = true; ch1 = sel.from.ch;}
|
|
850
|
-
}
|
|
851
|
-
if (badInnerHTML) {
|
|
852
|
-
scratch.innerHTML = lines[j].getHTML(ch1, ch2, true);
|
|
853
|
-
lineDiv.insertBefore(scratch.firstChild, nodeAfter);
|
|
854
|
-
}
|
|
1200
|
+
while (curNode) curNode = killNode(curNode);
|
|
1201
|
+
}
|
|
1202
|
+
// This pass fills in the lines that actually changed.
|
|
1203
|
+
var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
|
|
1204
|
+
var scratch = document.createElement("div");
|
|
1205
|
+
doc.iter(from, to, function(line) {
|
|
1206
|
+
if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
|
|
1207
|
+
if (!nextIntact || nextIntact.from > j) {
|
|
1208
|
+
if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
|
|
855
1209
|
else {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1210
|
+
var html = '<pre' + (line.className ? ' class="' + line.className + '"' : '') + '>'
|
|
1211
|
+
+ line.getHTML(makeTab) + '</pre>';
|
|
1212
|
+
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
|
1213
|
+
if (line.bgClassName)
|
|
1214
|
+
html = '<div style="position: relative"><pre class="' + line.bgClassName +
|
|
1215
|
+
'" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2"> </pre>' + html + "</div>";
|
|
859
1216
|
}
|
|
1217
|
+
scratch.innerHTML = html;
|
|
1218
|
+
lineDiv.insertBefore(scratch.firstChild, curNode);
|
|
1219
|
+
} else {
|
|
1220
|
+
curNode = curNode.nextSibling;
|
|
860
1221
|
}
|
|
861
|
-
|
|
862
|
-
}
|
|
1222
|
+
++j;
|
|
1223
|
+
});
|
|
863
1224
|
}
|
|
864
1225
|
|
|
865
1226
|
function updateGutter() {
|
|
866
1227
|
if (!options.gutter && !options.lineNumbers) return;
|
|
867
1228
|
var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
|
|
868
1229
|
gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
|
|
869
|
-
var html = [];
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1230
|
+
var html = [], i = showingFrom, normalNode;
|
|
1231
|
+
doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
|
|
1232
|
+
if (line.hidden) {
|
|
1233
|
+
html.push("<pre></pre>");
|
|
1234
|
+
} else {
|
|
1235
|
+
var marker = line.gutterMarker;
|
|
1236
|
+
var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null;
|
|
1237
|
+
if (marker && marker.text)
|
|
1238
|
+
text = marker.text.replace("%N%", text != null ? text : "");
|
|
1239
|
+
else if (text == null)
|
|
1240
|
+
text = "\u00a0";
|
|
1241
|
+
html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
|
|
1242
|
+
for (var j = 1; j < line.height; ++j) html.push("<br/> ");
|
|
1243
|
+
html.push("</pre>");
|
|
1244
|
+
if (!marker) normalNode = i;
|
|
1245
|
+
}
|
|
1246
|
+
++i;
|
|
1247
|
+
});
|
|
879
1248
|
gutter.style.display = "none";
|
|
880
1249
|
gutterText.innerHTML = html.join("");
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1250
|
+
// Make sure scrolling doesn't cause number gutter size to pop
|
|
1251
|
+
if (normalNode != null && options.lineNumbers) {
|
|
1252
|
+
var node = gutterText.childNodes[normalNode - showingFrom];
|
|
1253
|
+
var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = "";
|
|
1254
|
+
while (val.length + pad.length < minwidth) pad += "\u00a0";
|
|
1255
|
+
if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
|
|
1256
|
+
}
|
|
884
1257
|
gutter.style.display = "";
|
|
1258
|
+
var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;
|
|
885
1259
|
lineSpace.style.marginLeft = gutter.offsetWidth + "px";
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1260
|
+
gutterDirty = false;
|
|
1261
|
+
return resized;
|
|
1262
|
+
}
|
|
1263
|
+
function updateSelection() {
|
|
1264
|
+
var collapsed = posEq(sel.from, sel.to);
|
|
1265
|
+
var fromPos = localCoords(sel.from, true);
|
|
1266
|
+
var toPos = collapsed ? fromPos : localCoords(sel.to, true);
|
|
1267
|
+
var headPos = sel.inverted ? fromPos : toPos, th = textHeight();
|
|
1268
|
+
var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
|
|
1269
|
+
inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px";
|
|
1270
|
+
inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px";
|
|
1271
|
+
if (collapsed) {
|
|
1272
|
+
cursor.style.top = headPos.y + "px";
|
|
1273
|
+
cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px";
|
|
895
1274
|
cursor.style.display = "";
|
|
1275
|
+
selectionDiv.style.display = "none";
|
|
1276
|
+
} else {
|
|
1277
|
+
var sameLine = fromPos.y == toPos.y, html = "";
|
|
1278
|
+
var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
|
|
1279
|
+
var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
|
|
1280
|
+
function add(left, top, right, height) {
|
|
1281
|
+
var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
|
|
1282
|
+
: "right: " + right + "px";
|
|
1283
|
+
html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
|
|
1284
|
+
'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px"></div>';
|
|
1285
|
+
}
|
|
1286
|
+
if (sel.from.ch && fromPos.y >= 0) {
|
|
1287
|
+
var right = sameLine ? clientWidth - toPos.x : 0;
|
|
1288
|
+
add(fromPos.x, fromPos.y, right, th);
|
|
1289
|
+
}
|
|
1290
|
+
var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
|
|
1291
|
+
var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;
|
|
1292
|
+
if (middleHeight > 0.2 * th)
|
|
1293
|
+
add(0, middleStart, 0, middleHeight);
|
|
1294
|
+
if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
|
|
1295
|
+
add(0, toPos.y, clientWidth - toPos.x, th);
|
|
1296
|
+
selectionDiv.innerHTML = html;
|
|
1297
|
+
cursor.style.display = "none";
|
|
1298
|
+
selectionDiv.style.display = "";
|
|
896
1299
|
}
|
|
897
|
-
else cursor.style.display = "none";
|
|
898
1300
|
}
|
|
899
1301
|
|
|
1302
|
+
function setShift(val) {
|
|
1303
|
+
if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
|
|
1304
|
+
else shiftSelecting = null;
|
|
1305
|
+
}
|
|
900
1306
|
function setSelectionUser(from, to) {
|
|
901
1307
|
var sh = shiftSelecting && clipPos(shiftSelecting);
|
|
902
1308
|
if (sh) {
|
|
@@ -904,232 +1310,371 @@ var CodeMirror = (function() {
|
|
|
904
1310
|
else if (posLess(to, sh)) to = sh;
|
|
905
1311
|
}
|
|
906
1312
|
setSelection(from, to);
|
|
1313
|
+
userSelChange = true;
|
|
907
1314
|
}
|
|
908
1315
|
// Update the selection. Last two args are only used by
|
|
909
1316
|
// updateLines, since they have to be expressed in the line
|
|
910
1317
|
// numbers before the update.
|
|
911
1318
|
function setSelection(from, to, oldFrom, oldTo) {
|
|
1319
|
+
goalColumn = null;
|
|
1320
|
+
if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}
|
|
912
1321
|
if (posEq(sel.from, from) && posEq(sel.to, to)) return;
|
|
913
1322
|
if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
|
|
914
1323
|
|
|
1324
|
+
// Skip over hidden lines.
|
|
1325
|
+
if (from.line != oldFrom) {
|
|
1326
|
+
var from1 = skipHidden(from, oldFrom, sel.from.ch);
|
|
1327
|
+
// If there is no non-hidden line left, force visibility on current line
|
|
1328
|
+
if (!from1) setLineHidden(from.line, false);
|
|
1329
|
+
else from = from1;
|
|
1330
|
+
}
|
|
1331
|
+
if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
|
|
1332
|
+
|
|
915
1333
|
if (posEq(from, to)) sel.inverted = false;
|
|
916
1334
|
else if (posEq(from, sel.to)) sel.inverted = false;
|
|
917
1335
|
else if (posEq(to, sel.from)) sel.inverted = true;
|
|
918
1336
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
else {
|
|
931
|
-
if (!posEq(from, sel.from)) {
|
|
932
|
-
if (from.line < oldFrom)
|
|
933
|
-
changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1});
|
|
934
|
-
else
|
|
935
|
-
changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1});
|
|
936
|
-
}
|
|
937
|
-
if (!posEq(to, sel.to)) {
|
|
938
|
-
if (to.line < oldTo)
|
|
939
|
-
changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1});
|
|
940
|
-
else
|
|
941
|
-
changes.push({from: Math.max(from.line, oldTo), to: to.line + 1});
|
|
1337
|
+
if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
|
|
1338
|
+
var head = sel.inverted ? from : to;
|
|
1339
|
+
if (head.line != sel.from.line && sel.from.line < doc.size) {
|
|
1340
|
+
var oldLine = getLine(sel.from.line);
|
|
1341
|
+
if (/^\s+$/.test(oldLine.text))
|
|
1342
|
+
setTimeout(operation(function() {
|
|
1343
|
+
if (oldLine.parent && /^\s+$/.test(oldLine.text)) {
|
|
1344
|
+
var no = lineNo(oldLine);
|
|
1345
|
+
replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});
|
|
1346
|
+
}
|
|
1347
|
+
}, 10));
|
|
942
1348
|
}
|
|
943
1349
|
}
|
|
1350
|
+
|
|
944
1351
|
sel.from = from; sel.to = to;
|
|
945
1352
|
selectionChanged = true;
|
|
946
1353
|
}
|
|
1354
|
+
function skipHidden(pos, oldLine, oldCh) {
|
|
1355
|
+
function getNonHidden(dir) {
|
|
1356
|
+
var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;
|
|
1357
|
+
while (lNo != end) {
|
|
1358
|
+
var line = getLine(lNo);
|
|
1359
|
+
if (!line.hidden) {
|
|
1360
|
+
var ch = pos.ch;
|
|
1361
|
+
if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
|
|
1362
|
+
return {line: lNo, ch: ch};
|
|
1363
|
+
}
|
|
1364
|
+
lNo += dir;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
var line = getLine(pos.line);
|
|
1368
|
+
var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
|
|
1369
|
+
if (!line.hidden) return pos;
|
|
1370
|
+
if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
|
|
1371
|
+
else return getNonHidden(-1) || getNonHidden(1);
|
|
1372
|
+
}
|
|
947
1373
|
function setCursor(line, ch, user) {
|
|
948
1374
|
var pos = clipPos({line: line, ch: ch || 0});
|
|
949
1375
|
(user ? setSelectionUser : setSelection)(pos, pos);
|
|
950
1376
|
}
|
|
951
1377
|
|
|
952
|
-
function clipLine(n) {return Math.max(0, Math.min(n,
|
|
1378
|
+
function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}
|
|
953
1379
|
function clipPos(pos) {
|
|
954
1380
|
if (pos.line < 0) return {line: 0, ch: 0};
|
|
955
|
-
if (pos.line >=
|
|
956
|
-
var ch = pos.ch, linelen =
|
|
1381
|
+
if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};
|
|
1382
|
+
var ch = pos.ch, linelen = getLine(pos.line).text.length;
|
|
957
1383
|
if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
|
|
958
1384
|
else if (ch < 0) return {line: pos.line, ch: 0};
|
|
959
1385
|
else return pos;
|
|
960
1386
|
}
|
|
961
1387
|
|
|
962
|
-
function
|
|
963
|
-
var
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
function selectAll() {
|
|
971
|
-
var endLine = lines.length - 1;
|
|
972
|
-
setSelection({line: 0, ch: 0}, {line: endLine, ch: lines[endLine].text.length});
|
|
973
|
-
}
|
|
974
|
-
function selectWordAt(pos) {
|
|
975
|
-
var line = lines[pos.line].text;
|
|
976
|
-
var start = pos.ch, end = pos.ch;
|
|
977
|
-
while (start > 0 && /\w/.test(line.charAt(start - 1))) --start;
|
|
978
|
-
while (end < line.length && /\w/.test(line.charAt(end))) ++end;
|
|
979
|
-
setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
|
|
980
|
-
}
|
|
981
|
-
function selectLine(line) {
|
|
982
|
-
setSelectionUser({line: line, ch: 0}, {line: line, ch: lines[line].text.length});
|
|
983
|
-
}
|
|
984
|
-
function handleEnter() {
|
|
985
|
-
replaceSelection("\n", "end");
|
|
986
|
-
if (options.enterMode != "flat")
|
|
987
|
-
indentLine(sel.from.line, options.enterMode == "keep" ? "prev" : "smart");
|
|
988
|
-
}
|
|
989
|
-
function handleTab(shift) {
|
|
990
|
-
function indentSelected(mode) {
|
|
991
|
-
if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
|
|
992
|
-
var e = sel.to.line - (sel.to.ch ? 0 : 1);
|
|
993
|
-
for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
|
|
1388
|
+
function findPosH(dir, unit) {
|
|
1389
|
+
var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;
|
|
1390
|
+
var lineObj = getLine(line);
|
|
1391
|
+
function findNextLine() {
|
|
1392
|
+
for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {
|
|
1393
|
+
var lo = getLine(l);
|
|
1394
|
+
if (!lo.hidden) { line = l; lineObj = lo; return true; }
|
|
1395
|
+
}
|
|
994
1396
|
}
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1397
|
+
function moveOnce(boundToLine) {
|
|
1398
|
+
if (ch == (dir < 0 ? 0 : lineObj.text.length)) {
|
|
1399
|
+
if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;
|
|
1400
|
+
else return false;
|
|
1401
|
+
} else ch += dir;
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
if (unit == "char") moveOnce();
|
|
1405
|
+
else if (unit == "column") moveOnce(true);
|
|
1406
|
+
else if (unit == "word") {
|
|
1407
|
+
var sawWord = false;
|
|
1408
|
+
for (;;) {
|
|
1409
|
+
if (dir < 0) if (!moveOnce()) break;
|
|
1410
|
+
if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
|
|
1411
|
+
else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
|
|
1412
|
+
if (dir > 0) if (!moveOnce()) break;
|
|
1007
1413
|
}
|
|
1008
|
-
case "shift":
|
|
1009
|
-
indentSelected(shift ? "subtract" : "add");
|
|
1010
|
-
break;
|
|
1011
1414
|
}
|
|
1012
|
-
return
|
|
1415
|
+
return {line: line, ch: ch};
|
|
1416
|
+
}
|
|
1417
|
+
function moveH(dir, unit) {
|
|
1418
|
+
var pos = dir < 0 ? sel.from : sel.to;
|
|
1419
|
+
if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);
|
|
1420
|
+
setCursor(pos.line, pos.ch, true);
|
|
1421
|
+
}
|
|
1422
|
+
function deleteH(dir, unit) {
|
|
1423
|
+
if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to);
|
|
1424
|
+
else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to);
|
|
1425
|
+
else replaceRange("", sel.from, findPosH(dir, unit));
|
|
1426
|
+
userSelChange = true;
|
|
1427
|
+
}
|
|
1428
|
+
var goalColumn = null;
|
|
1429
|
+
function moveV(dir, unit) {
|
|
1430
|
+
var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
|
|
1431
|
+
if (goalColumn != null) pos.x = goalColumn;
|
|
1432
|
+
if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
|
|
1433
|
+
else if (unit == "line") dist = textHeight();
|
|
1434
|
+
var target = coordsChar(pos.x, pos.y + dist * dir + 2);
|
|
1435
|
+
if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
|
|
1436
|
+
setCursor(target.line, target.ch, true);
|
|
1437
|
+
goalColumn = pos.x;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
function findWordAt(pos) {
|
|
1441
|
+
var line = getLine(pos.line).text;
|
|
1442
|
+
var start = pos.ch, end = pos.ch;
|
|
1443
|
+
var check = isWordChar(line.charAt(start < line.length ? start : start - 1)) ?
|
|
1444
|
+
isWordChar : function(ch) {return !isWordChar(ch);};
|
|
1445
|
+
while (start > 0 && check(line.charAt(start - 1))) --start;
|
|
1446
|
+
while (end < line.length && check(line.charAt(end))) ++end;
|
|
1447
|
+
return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
|
|
1448
|
+
}
|
|
1449
|
+
function selectLine(line) {
|
|
1450
|
+
setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
|
|
1013
1451
|
}
|
|
1014
|
-
function
|
|
1015
|
-
|
|
1016
|
-
|
|
1452
|
+
function indentSelected(mode) {
|
|
1453
|
+
if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
|
|
1454
|
+
var e = sel.to.line - (sel.to.ch ? 0 : 1);
|
|
1455
|
+
for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
|
|
1017
1456
|
}
|
|
1018
1457
|
|
|
1019
1458
|
function indentLine(n, how) {
|
|
1459
|
+
if (!how) how = "add";
|
|
1020
1460
|
if (how == "smart") {
|
|
1021
1461
|
if (!mode.indent) how = "prev";
|
|
1022
1462
|
else var state = getStateBefore(n);
|
|
1023
1463
|
}
|
|
1024
1464
|
|
|
1025
|
-
var line =
|
|
1465
|
+
var line = getLine(n), curSpace = line.indentation(options.tabSize),
|
|
1466
|
+
curSpaceString = line.text.match(/^\s*/)[0], indentation;
|
|
1467
|
+
if (how == "smart") {
|
|
1468
|
+
indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
1469
|
+
if (indentation == Pass) how = "prev";
|
|
1470
|
+
}
|
|
1026
1471
|
if (how == "prev") {
|
|
1027
|
-
if (n) indentation =
|
|
1472
|
+
if (n) indentation = getLine(n-1).indentation(options.tabSize);
|
|
1028
1473
|
else indentation = 0;
|
|
1029
1474
|
}
|
|
1030
|
-
else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length));
|
|
1031
1475
|
else if (how == "add") indentation = curSpace + options.indentUnit;
|
|
1032
1476
|
else if (how == "subtract") indentation = curSpace - options.indentUnit;
|
|
1033
1477
|
indentation = Math.max(0, indentation);
|
|
1034
1478
|
var diff = indentation - curSpace;
|
|
1035
1479
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
var
|
|
1039
|
-
}
|
|
1040
|
-
else {
|
|
1041
|
-
var indentString = "", pos = 0;
|
|
1042
|
-
if (options.indentWithTabs)
|
|
1043
|
-
for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
|
|
1044
|
-
while (pos < indentation) {++pos; indentString += " ";}
|
|
1045
|
-
}
|
|
1480
|
+
var indentString = "", pos = 0;
|
|
1481
|
+
if (options.indentWithTabs)
|
|
1482
|
+
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
|
1483
|
+
while (pos < indentation) {++pos; indentString += " ";}
|
|
1046
1484
|
|
|
1047
1485
|
replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
|
|
1048
1486
|
}
|
|
1049
1487
|
|
|
1050
1488
|
function loadMode() {
|
|
1051
1489
|
mode = CodeMirror.getMode(options, options.mode);
|
|
1052
|
-
|
|
1053
|
-
lines[i].stateAfter = null;
|
|
1490
|
+
doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
|
|
1054
1491
|
work = [0];
|
|
1055
1492
|
startWorker();
|
|
1056
1493
|
}
|
|
1057
1494
|
function gutterChanged() {
|
|
1058
1495
|
var visible = options.gutter || options.lineNumbers;
|
|
1059
1496
|
gutter.style.display = visible ? "" : "none";
|
|
1060
|
-
if (visible)
|
|
1497
|
+
if (visible) gutterDirty = true;
|
|
1061
1498
|
else lineDiv.parentNode.style.marginLeft = 0;
|
|
1062
1499
|
}
|
|
1500
|
+
function wrappingChanged(from, to) {
|
|
1501
|
+
if (options.lineWrapping) {
|
|
1502
|
+
wrapper.className += " CodeMirror-wrap";
|
|
1503
|
+
var perLine = scroller.clientWidth / charWidth() - 3;
|
|
1504
|
+
doc.iter(0, doc.size, function(line) {
|
|
1505
|
+
if (line.hidden) return;
|
|
1506
|
+
var guess = Math.ceil(line.text.length / perLine) || 1;
|
|
1507
|
+
if (guess != 1) updateLineHeight(line, guess);
|
|
1508
|
+
});
|
|
1509
|
+
lineSpace.style.width = code.style.width = "";
|
|
1510
|
+
widthForcer.style.left = "";
|
|
1511
|
+
} else {
|
|
1512
|
+
wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
|
|
1513
|
+
maxLine = ""; maxLineChanged = true;
|
|
1514
|
+
doc.iter(0, doc.size, function(line) {
|
|
1515
|
+
if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
|
|
1516
|
+
if (line.text.length > maxLine.length) maxLine = line.text;
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
changes.push({from: 0, to: doc.size});
|
|
1520
|
+
}
|
|
1521
|
+
function makeTab(col) {
|
|
1522
|
+
var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
|
|
1523
|
+
if (cached) return cached;
|
|
1524
|
+
for (var str = '<span class="cm-tab">', i = 0; i < w; ++i) str += " ";
|
|
1525
|
+
return (tabCache[w] = {html: str + "</span>", width: w});
|
|
1526
|
+
}
|
|
1527
|
+
function themeChanged() {
|
|
1528
|
+
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
|
|
1529
|
+
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
|
|
1530
|
+
}
|
|
1531
|
+
function keyMapChanged() {
|
|
1532
|
+
var style = keyMap[options.keyMap].style;
|
|
1533
|
+
wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
|
|
1534
|
+
(style ? " cm-keymap-" + style : "");
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
function TextMarker() { this.set = []; }
|
|
1538
|
+
TextMarker.prototype.clear = operation(function() {
|
|
1539
|
+
var min = Infinity, max = -Infinity;
|
|
1540
|
+
for (var i = 0, e = this.set.length; i < e; ++i) {
|
|
1541
|
+
var line = this.set[i], mk = line.marked;
|
|
1542
|
+
if (!mk || !line.parent) continue;
|
|
1543
|
+
var lineN = lineNo(line);
|
|
1544
|
+
min = Math.min(min, lineN); max = Math.max(max, lineN);
|
|
1545
|
+
for (var j = 0; j < mk.length; ++j)
|
|
1546
|
+
if (mk[j].marker == this) mk.splice(j--, 1);
|
|
1547
|
+
}
|
|
1548
|
+
if (min != Infinity)
|
|
1549
|
+
changes.push({from: min, to: max + 1});
|
|
1550
|
+
});
|
|
1551
|
+
TextMarker.prototype.find = function() {
|
|
1552
|
+
var from, to;
|
|
1553
|
+
for (var i = 0, e = this.set.length; i < e; ++i) {
|
|
1554
|
+
var line = this.set[i], mk = line.marked;
|
|
1555
|
+
for (var j = 0; j < mk.length; ++j) {
|
|
1556
|
+
var mark = mk[j];
|
|
1557
|
+
if (mark.marker == this) {
|
|
1558
|
+
if (mark.from != null || mark.to != null) {
|
|
1559
|
+
var found = lineNo(line);
|
|
1560
|
+
if (found != null) {
|
|
1561
|
+
if (mark.from != null) from = {line: found, ch: mark.from};
|
|
1562
|
+
if (mark.to != null) to = {line: found, ch: mark.to};
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
return {from: from, to: to};
|
|
1569
|
+
};
|
|
1063
1570
|
|
|
1064
1571
|
function markText(from, to, className) {
|
|
1065
1572
|
from = clipPos(from); to = clipPos(to);
|
|
1066
|
-
var
|
|
1573
|
+
var tm = new TextMarker();
|
|
1574
|
+
if (!posLess(from, to)) return tm;
|
|
1067
1575
|
function add(line, from, to, className) {
|
|
1068
|
-
|
|
1069
|
-
mark.line = line;
|
|
1070
|
-
accum.push(mark);
|
|
1576
|
+
getLine(line).addMark(new MarkedText(from, to, className, tm));
|
|
1071
1577
|
}
|
|
1072
1578
|
if (from.line == to.line) add(from.line, from.ch, to.ch, className);
|
|
1073
1579
|
else {
|
|
1074
1580
|
add(from.line, from.ch, null, className);
|
|
1075
1581
|
for (var i = from.line + 1, e = to.line; i < e; ++i)
|
|
1076
|
-
add(i,
|
|
1077
|
-
add(to.line,
|
|
1582
|
+
add(i, null, null, className);
|
|
1583
|
+
add(to.line, null, to.ch, className);
|
|
1078
1584
|
}
|
|
1079
1585
|
changes.push({from: from.line, to: to.line + 1});
|
|
1080
|
-
return
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1586
|
+
return tm;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
function setBookmark(pos) {
|
|
1590
|
+
pos = clipPos(pos);
|
|
1591
|
+
var bm = new Bookmark(pos.ch);
|
|
1592
|
+
getLine(pos.line).addMark(bm);
|
|
1593
|
+
return bm;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
function findMarksAt(pos) {
|
|
1597
|
+
pos = clipPos(pos);
|
|
1598
|
+
var markers = [], marked = getLine(pos.line).marked;
|
|
1599
|
+
if (!marked) return markers;
|
|
1600
|
+
for (var i = 0, e = marked.length; i < e; ++i) {
|
|
1601
|
+
var m = marked[i];
|
|
1602
|
+
if ((m.from == null || m.from <= pos.ch) &&
|
|
1603
|
+
(m.to == null || m.to >= pos.ch))
|
|
1604
|
+
markers.push(m.marker || m);
|
|
1605
|
+
}
|
|
1606
|
+
return markers;
|
|
1092
1607
|
}
|
|
1093
1608
|
|
|
1094
1609
|
function addGutterMarker(line, text, className) {
|
|
1095
|
-
if (typeof line == "number") line =
|
|
1610
|
+
if (typeof line == "number") line = getLine(clipLine(line));
|
|
1096
1611
|
line.gutterMarker = {text: text, style: className};
|
|
1097
|
-
|
|
1612
|
+
gutterDirty = true;
|
|
1098
1613
|
return line;
|
|
1099
1614
|
}
|
|
1100
1615
|
function removeGutterMarker(line) {
|
|
1101
|
-
if (typeof line == "number") line =
|
|
1616
|
+
if (typeof line == "number") line = getLine(clipLine(line));
|
|
1102
1617
|
line.gutterMarker = null;
|
|
1103
|
-
|
|
1618
|
+
gutterDirty = true;
|
|
1104
1619
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
}
|
|
1114
|
-
if (line.className != className) {
|
|
1115
|
-
line.className = className;
|
|
1116
|
-
changes.push({from: no, to: no + 1});
|
|
1117
|
-
}
|
|
1620
|
+
|
|
1621
|
+
function changeLine(handle, op) {
|
|
1622
|
+
var no = handle, line = handle;
|
|
1623
|
+
if (typeof handle == "number") line = getLine(clipLine(handle));
|
|
1624
|
+
else no = lineNo(handle);
|
|
1625
|
+
if (no == null) return null;
|
|
1626
|
+
if (op(line, no)) changes.push({from: no, to: no + 1});
|
|
1627
|
+
else return null;
|
|
1118
1628
|
return line;
|
|
1119
1629
|
}
|
|
1630
|
+
function setLineClass(handle, className, bgClassName) {
|
|
1631
|
+
return changeLine(handle, function(line) {
|
|
1632
|
+
if (line.className != className || line.bgClassName != bgClassName) {
|
|
1633
|
+
line.className = className;
|
|
1634
|
+
line.bgClassName = bgClassName;
|
|
1635
|
+
return true;
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
function setLineHidden(handle, hidden) {
|
|
1640
|
+
return changeLine(handle, function(line, no) {
|
|
1641
|
+
if (line.hidden != hidden) {
|
|
1642
|
+
line.hidden = hidden;
|
|
1643
|
+
if (!options.lineWrapping) {
|
|
1644
|
+
var l = line.text;
|
|
1645
|
+
if (hidden && l.length == maxLine.length) {
|
|
1646
|
+
updateMaxLine = true;
|
|
1647
|
+
} else if (!hidden && l.length > maxLine.length) {
|
|
1648
|
+
maxLine = l; updateMaxLine = false;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
updateLineHeight(line, hidden ? 0 : 1);
|
|
1652
|
+
var fline = sel.from.line, tline = sel.to.line;
|
|
1653
|
+
if (hidden && (fline == no || tline == no)) {
|
|
1654
|
+
var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
|
|
1655
|
+
var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
|
|
1656
|
+
// Can't hide the last visible line, we'd have no place to put the cursor
|
|
1657
|
+
if (!to) return;
|
|
1658
|
+
setSelection(from, to);
|
|
1659
|
+
}
|
|
1660
|
+
return (gutterDirty = true);
|
|
1661
|
+
}
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1120
1664
|
|
|
1121
1665
|
function lineInfo(line) {
|
|
1122
1666
|
if (typeof line == "number") {
|
|
1667
|
+
if (!isLine(line)) return null;
|
|
1123
1668
|
var n = line;
|
|
1124
|
-
line =
|
|
1669
|
+
line = getLine(line);
|
|
1125
1670
|
if (!line) return null;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
if (n == -1) return null;
|
|
1671
|
+
} else {
|
|
1672
|
+
var n = lineNo(line);
|
|
1673
|
+
if (n == null) return null;
|
|
1130
1674
|
}
|
|
1131
1675
|
var marker = line.gutterMarker;
|
|
1132
|
-
return {line: n, text: line.text, markerText: marker && marker.text,
|
|
1676
|
+
return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
|
|
1677
|
+
markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
|
|
1133
1678
|
}
|
|
1134
1679
|
|
|
1135
1680
|
function stringWidth(str) {
|
|
@@ -1139,21 +1684,15 @@ var CodeMirror = (function() {
|
|
|
1139
1684
|
}
|
|
1140
1685
|
// These are used to go from pixel positions to character
|
|
1141
1686
|
// positions, taking varying character widths into account.
|
|
1142
|
-
function charX(line, pos) {
|
|
1143
|
-
if (pos == 0) return 0;
|
|
1144
|
-
measure.innerHTML = "<pre><span>" + lines[line].getHTML(null, null, false, pos) + "</span></pre>";
|
|
1145
|
-
return measure.firstChild.firstChild.offsetWidth;
|
|
1146
|
-
}
|
|
1147
1687
|
function charFromX(line, x) {
|
|
1148
1688
|
if (x <= 0) return 0;
|
|
1149
|
-
var lineObj =
|
|
1689
|
+
var lineObj = getLine(line), text = lineObj.text;
|
|
1150
1690
|
function getX(len) {
|
|
1151
|
-
|
|
1152
|
-
return measure.firstChild.firstChild.offsetWidth;
|
|
1691
|
+
return measureLine(lineObj, len).left;
|
|
1153
1692
|
}
|
|
1154
1693
|
var from = 0, fromX = 0, to = text.length, toX;
|
|
1155
1694
|
// Guess a suitable upper bound for our search.
|
|
1156
|
-
var estimated = Math.min(to, Math.ceil(x /
|
|
1695
|
+
var estimated = Math.min(to, Math.ceil(x / charWidth()));
|
|
1157
1696
|
for (;;) {
|
|
1158
1697
|
var estX = getX(estimated);
|
|
1159
1698
|
if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
|
|
@@ -1172,20 +1711,95 @@ var CodeMirror = (function() {
|
|
|
1172
1711
|
}
|
|
1173
1712
|
}
|
|
1174
1713
|
|
|
1714
|
+
var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
|
|
1715
|
+
function measureLine(line, ch) {
|
|
1716
|
+
if (ch == 0) return {top: 0, left: 0};
|
|
1717
|
+
var wbr = options.lineWrapping && ch < line.text.length &&
|
|
1718
|
+
spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
|
|
1719
|
+
measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch, tempId, wbr) + "</pre>";
|
|
1720
|
+
var elt = document.getElementById(tempId);
|
|
1721
|
+
var top = elt.offsetTop, left = elt.offsetLeft;
|
|
1722
|
+
// Older IEs report zero offsets for spans directly after a wrap
|
|
1723
|
+
if (ie && top == 0 && left == 0) {
|
|
1724
|
+
var backup = document.createElement("span");
|
|
1725
|
+
backup.innerHTML = "x";
|
|
1726
|
+
elt.parentNode.insertBefore(backup, elt.nextSibling);
|
|
1727
|
+
top = backup.offsetTop;
|
|
1728
|
+
}
|
|
1729
|
+
return {top: top, left: left};
|
|
1730
|
+
}
|
|
1175
1731
|
function localCoords(pos, inLineWrap) {
|
|
1176
|
-
var lh =
|
|
1177
|
-
|
|
1732
|
+
var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));
|
|
1733
|
+
if (pos.ch == 0) x = 0;
|
|
1734
|
+
else {
|
|
1735
|
+
var sp = measureLine(getLine(pos.line), pos.ch);
|
|
1736
|
+
x = sp.left;
|
|
1737
|
+
if (options.lineWrapping) y += Math.max(0, sp.top);
|
|
1738
|
+
}
|
|
1739
|
+
return {x: x, y: y, yBot: y + lh};
|
|
1740
|
+
}
|
|
1741
|
+
// Coords must be lineSpace-local
|
|
1742
|
+
function coordsChar(x, y) {
|
|
1743
|
+
if (y < 0) y = 0;
|
|
1744
|
+
var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);
|
|
1745
|
+
var lineNo = lineAtHeight(doc, heightPos);
|
|
1746
|
+
if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};
|
|
1747
|
+
var lineObj = getLine(lineNo), text = lineObj.text;
|
|
1748
|
+
var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;
|
|
1749
|
+
if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};
|
|
1750
|
+
function getX(len) {
|
|
1751
|
+
var sp = measureLine(lineObj, len);
|
|
1752
|
+
if (tw) {
|
|
1753
|
+
var off = Math.round(sp.top / th);
|
|
1754
|
+
return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);
|
|
1755
|
+
}
|
|
1756
|
+
return sp.left;
|
|
1757
|
+
}
|
|
1758
|
+
var from = 0, fromX = 0, to = text.length, toX;
|
|
1759
|
+
// Guess a suitable upper bound for our search.
|
|
1760
|
+
var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));
|
|
1761
|
+
for (;;) {
|
|
1762
|
+
var estX = getX(estimated);
|
|
1763
|
+
if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
|
|
1764
|
+
else {toX = estX; to = estimated; break;}
|
|
1765
|
+
}
|
|
1766
|
+
if (x > toX) return {line: lineNo, ch: to};
|
|
1767
|
+
// Try to guess a suitable lower bound as well.
|
|
1768
|
+
estimated = Math.floor(to * 0.8); estX = getX(estimated);
|
|
1769
|
+
if (estX < x) {from = estimated; fromX = estX;}
|
|
1770
|
+
// Do a binary search between these bounds.
|
|
1771
|
+
for (;;) {
|
|
1772
|
+
if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};
|
|
1773
|
+
var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
|
|
1774
|
+
if (middleX > x) {to = middle; toX = middleX;}
|
|
1775
|
+
else {from = middle; fromX = middleX;}
|
|
1776
|
+
}
|
|
1178
1777
|
}
|
|
1179
1778
|
function pageCoords(pos) {
|
|
1180
1779
|
var local = localCoords(pos, true), off = eltOffset(lineSpace);
|
|
1181
1780
|
return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
|
|
1182
1781
|
}
|
|
1183
1782
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
if (
|
|
1187
|
-
|
|
1188
|
-
|
|
1783
|
+
var cachedHeight, cachedHeightFor, measureText;
|
|
1784
|
+
function textHeight() {
|
|
1785
|
+
if (measureText == null) {
|
|
1786
|
+
measureText = "<pre>";
|
|
1787
|
+
for (var i = 0; i < 49; ++i) measureText += "x<br/>";
|
|
1788
|
+
measureText += "x</pre>";
|
|
1789
|
+
}
|
|
1790
|
+
var offsetHeight = lineDiv.clientHeight;
|
|
1791
|
+
if (offsetHeight == cachedHeightFor) return cachedHeight;
|
|
1792
|
+
cachedHeightFor = offsetHeight;
|
|
1793
|
+
measure.innerHTML = measureText;
|
|
1794
|
+
cachedHeight = measure.firstChild.offsetHeight / 50 || 1;
|
|
1795
|
+
measure.innerHTML = "";
|
|
1796
|
+
return cachedHeight;
|
|
1797
|
+
}
|
|
1798
|
+
var cachedWidth, cachedWidthFor = 0;
|
|
1799
|
+
function charWidth() {
|
|
1800
|
+
if (scroller.clientWidth == cachedWidthFor) return cachedWidth;
|
|
1801
|
+
cachedWidthFor = scroller.clientWidth;
|
|
1802
|
+
return (cachedWidth = stringWidth("x"));
|
|
1189
1803
|
}
|
|
1190
1804
|
function paddingTop() {return lineSpace.offsetTop;}
|
|
1191
1805
|
function paddingLeft() {return lineSpace.offsetLeft;}
|
|
@@ -1200,12 +1814,11 @@ var CodeMirror = (function() {
|
|
|
1200
1814
|
if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))
|
|
1201
1815
|
return null;
|
|
1202
1816
|
var offL = eltOffset(lineSpace, true);
|
|
1203
|
-
|
|
1204
|
-
return clipPos({line: line, ch: charFromX(clipLine(line), x - offL.left)});
|
|
1817
|
+
return coordsChar(x - offL.left, y - offL.top);
|
|
1205
1818
|
}
|
|
1206
1819
|
function onContextMenu(e) {
|
|
1207
|
-
var pos = posFromMouse(e);
|
|
1208
|
-
if (!pos ||
|
|
1820
|
+
var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
|
|
1821
|
+
if (!pos || opera) return; // Opera is difficult.
|
|
1209
1822
|
if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
|
|
1210
1823
|
operation(setCursor)(pos.line, pos.ch);
|
|
1211
1824
|
|
|
@@ -1217,25 +1830,25 @@ var CodeMirror = (function() {
|
|
|
1217
1830
|
leaveInputAlone = true;
|
|
1218
1831
|
var val = input.value = getSelection();
|
|
1219
1832
|
focusInput();
|
|
1220
|
-
|
|
1833
|
+
selectInput(input);
|
|
1221
1834
|
function rehide() {
|
|
1222
1835
|
var newVal = splitLines(input.value).join("\n");
|
|
1223
|
-
if (newVal != val) operation(replaceSelection)(newVal, "end");
|
|
1836
|
+
if (newVal != val && !options.readOnly) operation(replaceSelection)(newVal, "end");
|
|
1224
1837
|
inputDiv.style.position = "relative";
|
|
1225
1838
|
input.style.cssText = oldCSS;
|
|
1839
|
+
if (ie_lt9) scrollbar.scrollTop = scrollPos;
|
|
1226
1840
|
leaveInputAlone = false;
|
|
1227
|
-
|
|
1841
|
+
resetInput(true);
|
|
1228
1842
|
slowPoll();
|
|
1229
1843
|
}
|
|
1230
|
-
|
|
1844
|
+
|
|
1231
1845
|
if (gecko) {
|
|
1232
1846
|
e_stop(e);
|
|
1233
1847
|
var mouseup = connect(window, "mouseup", function() {
|
|
1234
1848
|
mouseup();
|
|
1235
1849
|
setTimeout(rehide, 20);
|
|
1236
1850
|
}, true);
|
|
1237
|
-
}
|
|
1238
|
-
else {
|
|
1851
|
+
} else {
|
|
1239
1852
|
setTimeout(rehide, 50);
|
|
1240
1853
|
}
|
|
1241
1854
|
}
|
|
@@ -1252,7 +1865,7 @@ var CodeMirror = (function() {
|
|
|
1252
1865
|
|
|
1253
1866
|
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
|
|
1254
1867
|
function matchBrackets(autoclear) {
|
|
1255
|
-
var head = sel.inverted ? sel.from : sel.to, line =
|
|
1868
|
+
var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;
|
|
1256
1869
|
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
|
|
1257
1870
|
if (!match) return;
|
|
1258
1871
|
var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
|
|
@@ -1265,7 +1878,7 @@ var CodeMirror = (function() {
|
|
|
1265
1878
|
var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
|
|
1266
1879
|
for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
|
|
1267
1880
|
var text = st[i];
|
|
1268
|
-
if (st[i+1] !=
|
|
1881
|
+
if (st[i+1] != style) {pos += d * text.length; continue;}
|
|
1269
1882
|
for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
|
|
1270
1883
|
if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
|
|
1271
1884
|
var match = matching[cur];
|
|
@@ -1276,18 +1889,16 @@ var CodeMirror = (function() {
|
|
|
1276
1889
|
}
|
|
1277
1890
|
}
|
|
1278
1891
|
}
|
|
1279
|
-
for (var i = head.line, e = forward ? Math.min(i + 100,
|
|
1280
|
-
var line =
|
|
1892
|
+
for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {
|
|
1893
|
+
var line = getLine(i), first = i == head.line;
|
|
1281
1894
|
var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
|
|
1282
1895
|
if (found) break;
|
|
1283
1896
|
}
|
|
1284
1897
|
if (!found) found = {pos: null, match: false};
|
|
1285
1898
|
var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
|
|
1286
1899
|
var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
|
|
1287
|
-
two = found.pos != null
|
|
1288
|
-
|
|
1289
|
-
: function() {};
|
|
1290
|
-
var clear = operation(function(){one(); two();});
|
|
1900
|
+
two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
|
|
1901
|
+
var clear = operation(function(){one.clear(); two && two.clear();});
|
|
1291
1902
|
if (autoclear) setTimeout(clear, 800);
|
|
1292
1903
|
else bracketHighlighted = clear;
|
|
1293
1904
|
}
|
|
@@ -1301,9 +1912,9 @@ var CodeMirror = (function() {
|
|
|
1301
1912
|
var minindent, minline;
|
|
1302
1913
|
for (var search = n, lim = n - 40; search > lim; --search) {
|
|
1303
1914
|
if (search == 0) return 0;
|
|
1304
|
-
var line =
|
|
1915
|
+
var line = getLine(search-1);
|
|
1305
1916
|
if (line.stateAfter) return search;
|
|
1306
|
-
var indented = line.indentation();
|
|
1917
|
+
var indented = line.indentation(options.tabSize);
|
|
1307
1918
|
if (minline == null || minindent > indented) {
|
|
1308
1919
|
minline = search - 1;
|
|
1309
1920
|
minindent = indented;
|
|
@@ -1312,55 +1923,62 @@ var CodeMirror = (function() {
|
|
|
1312
1923
|
return minline;
|
|
1313
1924
|
}
|
|
1314
1925
|
function getStateBefore(n) {
|
|
1315
|
-
var start = findStartLine(n), state = start &&
|
|
1926
|
+
var start = findStartLine(n), state = start && getLine(start-1).stateAfter;
|
|
1316
1927
|
if (!state) state = startState(mode);
|
|
1317
1928
|
else state = copyState(mode, state);
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
line.highlight(mode, state);
|
|
1929
|
+
doc.iter(start, n, function(line) {
|
|
1930
|
+
line.highlight(mode, state, options.tabSize);
|
|
1321
1931
|
line.stateAfter = copyState(mode, state);
|
|
1322
|
-
}
|
|
1323
|
-
if (
|
|
1932
|
+
});
|
|
1933
|
+
if (start < n) changes.push({from: start, to: n});
|
|
1934
|
+
if (n < doc.size && !getLine(n).stateAfter) work.push(n);
|
|
1324
1935
|
return state;
|
|
1325
1936
|
}
|
|
1326
1937
|
function highlightLines(start, end) {
|
|
1327
1938
|
var state = getStateBefore(start);
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
line.highlight(mode, state);
|
|
1939
|
+
doc.iter(start, end, function(line) {
|
|
1940
|
+
line.highlight(mode, state, options.tabSize);
|
|
1331
1941
|
line.stateAfter = copyState(mode, state);
|
|
1332
|
-
}
|
|
1942
|
+
});
|
|
1333
1943
|
}
|
|
1334
1944
|
function highlightWorker() {
|
|
1335
1945
|
var end = +new Date + options.workTime;
|
|
1336
1946
|
var foundWork = work.length;
|
|
1337
1947
|
while (work.length) {
|
|
1338
|
-
if (!
|
|
1948
|
+
if (!getLine(showingFrom).stateAfter) var task = showingFrom;
|
|
1339
1949
|
else var task = work.pop();
|
|
1340
|
-
if (task >=
|
|
1341
|
-
var start = findStartLine(task), state = start &&
|
|
1950
|
+
if (task >= doc.size) continue;
|
|
1951
|
+
var start = findStartLine(task), state = start && getLine(start-1).stateAfter;
|
|
1342
1952
|
if (state) state = copyState(mode, state);
|
|
1343
1953
|
else state = startState(mode);
|
|
1344
1954
|
|
|
1345
|
-
var unchanged = 0, compare = mode.compareStates, realChange = false
|
|
1346
|
-
|
|
1347
|
-
|
|
1955
|
+
var unchanged = 0, compare = mode.compareStates, realChange = false,
|
|
1956
|
+
i = start, bail = false;
|
|
1957
|
+
doc.iter(i, doc.size, function(line) {
|
|
1958
|
+
var hadState = line.stateAfter;
|
|
1348
1959
|
if (+new Date > end) {
|
|
1349
1960
|
work.push(i);
|
|
1350
1961
|
startWorker(options.workDelay);
|
|
1351
1962
|
if (realChange) changes.push({from: task, to: i + 1});
|
|
1352
|
-
return;
|
|
1963
|
+
return (bail = true);
|
|
1353
1964
|
}
|
|
1354
|
-
var changed = line.highlight(mode, state);
|
|
1965
|
+
var changed = line.highlight(mode, state, options.tabSize);
|
|
1355
1966
|
if (changed) realChange = true;
|
|
1356
1967
|
line.stateAfter = copyState(mode, state);
|
|
1968
|
+
var done = null;
|
|
1357
1969
|
if (compare) {
|
|
1358
|
-
|
|
1359
|
-
|
|
1970
|
+
var same = hadState && compare(hadState, state);
|
|
1971
|
+
if (same != Pass) done = !!same;
|
|
1972
|
+
}
|
|
1973
|
+
if (done == null) {
|
|
1360
1974
|
if (changed !== false || !hadState) unchanged = 0;
|
|
1361
|
-
else if (++unchanged > 3)
|
|
1975
|
+
else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
|
|
1976
|
+
done = true;
|
|
1362
1977
|
}
|
|
1363
|
-
|
|
1978
|
+
if (done) return true;
|
|
1979
|
+
++i;
|
|
1980
|
+
});
|
|
1981
|
+
if (bail) return;
|
|
1364
1982
|
if (realChange) changes.push({from: task, to: i + 1});
|
|
1365
1983
|
}
|
|
1366
1984
|
if (foundWork && options.onHighlightComplete)
|
|
@@ -1376,32 +1994,46 @@ var CodeMirror = (function() {
|
|
|
1376
1994
|
// be awkward, slow, and error-prone), but instead updates are
|
|
1377
1995
|
// batched and then all combined and executed at once.
|
|
1378
1996
|
function startOperation() {
|
|
1379
|
-
updateInput =
|
|
1997
|
+
updateInput = userSelChange = textChanged = null;
|
|
1998
|
+
changes = []; selectionChanged = false; callbacks = [];
|
|
1380
1999
|
}
|
|
1381
2000
|
function endOperation() {
|
|
1382
|
-
|
|
1383
|
-
if (
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
2001
|
+
if (updateMaxLine) computeMaxLength();
|
|
2002
|
+
if (maxLineChanged && !options.lineWrapping) {
|
|
2003
|
+
var cursorWidth = widthForcer.offsetWidth, left = stringWidth(maxLine);
|
|
2004
|
+
widthForcer.style.left = left + "px";
|
|
2005
|
+
lineSpace.style.minWidth = (left + cursorWidth) + "px";
|
|
2006
|
+
maxLineChanged = false;
|
|
2007
|
+
}
|
|
2008
|
+
var newScrollPos, updated;
|
|
2009
|
+
if (selectionChanged) {
|
|
2010
|
+
var coords = calculateCursorCoords();
|
|
2011
|
+
newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
|
|
2012
|
+
}
|
|
2013
|
+
if (changes.length) updated = updateDisplay(changes, true, (newScrollPos ? newScrollPos.scrollTop : null));
|
|
2014
|
+
else {
|
|
2015
|
+
if (selectionChanged) updateSelection();
|
|
2016
|
+
if (gutterDirty) updateGutter();
|
|
2017
|
+
}
|
|
2018
|
+
if (newScrollPos) scrollCursorIntoView();
|
|
1387
2019
|
if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
|
|
1388
2020
|
|
|
1389
|
-
// updateInput can be set to a boolean value to force/prevent an
|
|
1390
|
-
// update.
|
|
1391
2021
|
if (focused && !leaveInputAlone &&
|
|
1392
2022
|
(updateInput === true || (updateInput !== false && selectionChanged)))
|
|
1393
|
-
|
|
2023
|
+
resetInput(userSelChange);
|
|
1394
2024
|
|
|
1395
2025
|
if (selectionChanged && options.matchBrackets)
|
|
1396
2026
|
setTimeout(operation(function() {
|
|
1397
2027
|
if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
|
|
1398
|
-
matchBrackets(false);
|
|
2028
|
+
if (posEq(sel.from, sel.to)) matchBrackets(false);
|
|
1399
2029
|
}), 20);
|
|
1400
|
-
var
|
|
1401
|
-
if (
|
|
2030
|
+
var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks
|
|
2031
|
+
if (textChanged && options.onChange && instance)
|
|
2032
|
+
options.onChange(instance, textChanged);
|
|
2033
|
+
if (sc && options.onCursorActivity)
|
|
1402
2034
|
options.onCursorActivity(instance);
|
|
1403
|
-
|
|
1404
|
-
|
|
2035
|
+
for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
|
|
2036
|
+
if (updated && options.onUpdate) options.onUpdate(instance);
|
|
1405
2037
|
}
|
|
1406
2038
|
var nestedOperation = 0;
|
|
1407
2039
|
function operation(f) {
|
|
@@ -1413,120 +2045,11 @@ var CodeMirror = (function() {
|
|
|
1413
2045
|
};
|
|
1414
2046
|
}
|
|
1415
2047
|
|
|
1416
|
-
function
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
if (pos && typeof pos == "object") pos = clipPos(pos);
|
|
1421
|
-
else pos = {line: 0, ch: 0};
|
|
1422
|
-
this.pos = {from: pos, to: pos};
|
|
1423
|
-
|
|
1424
|
-
// The matches method is filled in based on the type of query.
|
|
1425
|
-
// It takes a position and a direction, and returns an object
|
|
1426
|
-
// describing the next occurrence of the query, or null if no
|
|
1427
|
-
// more matches were found.
|
|
1428
|
-
if (typeof query != "string") // Regexp match
|
|
1429
|
-
this.matches = function(reverse, pos) {
|
|
1430
|
-
if (reverse) {
|
|
1431
|
-
var line = lines[pos.line].text.slice(0, pos.ch), match = line.match(query), start = 0;
|
|
1432
|
-
while (match) {
|
|
1433
|
-
var ind = line.indexOf(match[0]);
|
|
1434
|
-
start += ind;
|
|
1435
|
-
line = line.slice(ind + 1);
|
|
1436
|
-
var newmatch = line.match(query);
|
|
1437
|
-
if (newmatch) match = newmatch;
|
|
1438
|
-
else break;
|
|
1439
|
-
start++;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
else {
|
|
1443
|
-
var line = lines[pos.line].text.slice(pos.ch), match = line.match(query),
|
|
1444
|
-
start = match && pos.ch + line.indexOf(match[0]);
|
|
1445
|
-
}
|
|
1446
|
-
if (match)
|
|
1447
|
-
return {from: {line: pos.line, ch: start},
|
|
1448
|
-
to: {line: pos.line, ch: start + match[0].length},
|
|
1449
|
-
match: match};
|
|
1450
|
-
};
|
|
1451
|
-
else { // String query
|
|
1452
|
-
if (caseFold) query = query.toLowerCase();
|
|
1453
|
-
var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
|
|
1454
|
-
var target = query.split("\n");
|
|
1455
|
-
// Different methods for single-line and multi-line queries
|
|
1456
|
-
if (target.length == 1)
|
|
1457
|
-
this.matches = function(reverse, pos) {
|
|
1458
|
-
var line = fold(lines[pos.line].text), len = query.length, match;
|
|
1459
|
-
if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
|
|
1460
|
-
: (match = line.indexOf(query, pos.ch)) != -1)
|
|
1461
|
-
return {from: {line: pos.line, ch: match},
|
|
1462
|
-
to: {line: pos.line, ch: match + len}};
|
|
1463
|
-
};
|
|
1464
|
-
else
|
|
1465
|
-
this.matches = function(reverse, pos) {
|
|
1466
|
-
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(lines[ln].text);
|
|
1467
|
-
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
|
|
1468
|
-
if (reverse ? offsetA >= pos.ch || offsetA != match.length
|
|
1469
|
-
: offsetA <= pos.ch || offsetA != line.length - match.length)
|
|
1470
|
-
return;
|
|
1471
|
-
for (;;) {
|
|
1472
|
-
if (reverse ? !ln : ln == lines.length - 1) return;
|
|
1473
|
-
line = fold(lines[ln += reverse ? -1 : 1].text);
|
|
1474
|
-
match = target[reverse ? --idx : ++idx];
|
|
1475
|
-
if (idx > 0 && idx < target.length - 1) {
|
|
1476
|
-
if (line != match) return;
|
|
1477
|
-
else continue;
|
|
1478
|
-
}
|
|
1479
|
-
var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
|
|
1480
|
-
if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
|
|
1481
|
-
return;
|
|
1482
|
-
var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};
|
|
1483
|
-
return {from: reverse ? end : start, to: reverse ? start : end};
|
|
1484
|
-
}
|
|
1485
|
-
};
|
|
1486
|
-
}
|
|
2048
|
+
function compoundChange(f) {
|
|
2049
|
+
history.startCompound();
|
|
2050
|
+
try { return f(); } finally { history.endCompound(); }
|
|
1487
2051
|
}
|
|
1488
2052
|
|
|
1489
|
-
SearchCursor.prototype = {
|
|
1490
|
-
findNext: function() {return this.find(false);},
|
|
1491
|
-
findPrevious: function() {return this.find(true);},
|
|
1492
|
-
|
|
1493
|
-
find: function(reverse) {
|
|
1494
|
-
var self = this, pos = clipPos(reverse ? this.pos.from : this.pos.to);
|
|
1495
|
-
function savePosAndFail(line) {
|
|
1496
|
-
var pos = {line: line, ch: 0};
|
|
1497
|
-
self.pos = {from: pos, to: pos};
|
|
1498
|
-
self.atOccurrence = false;
|
|
1499
|
-
return false;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
for (;;) {
|
|
1503
|
-
if (this.pos = this.matches(reverse, pos)) {
|
|
1504
|
-
this.atOccurrence = true;
|
|
1505
|
-
return this.pos.match || true;
|
|
1506
|
-
}
|
|
1507
|
-
if (reverse) {
|
|
1508
|
-
if (!pos.line) return savePosAndFail(0);
|
|
1509
|
-
pos = {line: pos.line-1, ch: lines[pos.line-1].text.length};
|
|
1510
|
-
}
|
|
1511
|
-
else {
|
|
1512
|
-
if (pos.line == lines.length - 1) return savePosAndFail(lines.length);
|
|
1513
|
-
pos = {line: pos.line+1, ch: 0};
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
},
|
|
1517
|
-
|
|
1518
|
-
from: function() {if (this.atOccurrence) return copyPos(this.pos.from);},
|
|
1519
|
-
to: function() {if (this.atOccurrence) return copyPos(this.pos.to);},
|
|
1520
|
-
|
|
1521
|
-
replace: function(newText) {
|
|
1522
|
-
var self = this;
|
|
1523
|
-
if (this.atOccurrence)
|
|
1524
|
-
operation(function() {
|
|
1525
|
-
self.pos.to = replaceRange(newText, self.pos.from, self.pos.to);
|
|
1526
|
-
})();
|
|
1527
|
-
}
|
|
1528
|
-
};
|
|
1529
|
-
|
|
1530
2053
|
for (var ext in extensions)
|
|
1531
2054
|
if (extensions.propertyIsEnumerable(ext) &&
|
|
1532
2055
|
!instance.propertyIsEnumerable(ext))
|
|
@@ -1541,50 +2064,67 @@ var CodeMirror = (function() {
|
|
|
1541
2064
|
theme: "default",
|
|
1542
2065
|
indentUnit: 2,
|
|
1543
2066
|
indentWithTabs: false,
|
|
1544
|
-
|
|
1545
|
-
|
|
2067
|
+
smartIndent: true,
|
|
2068
|
+
tabSize: 4,
|
|
2069
|
+
keyMap: "default",
|
|
2070
|
+
extraKeys: null,
|
|
1546
2071
|
electricChars: true,
|
|
2072
|
+
autoClearEmptyLines: false,
|
|
1547
2073
|
onKeyEvent: null,
|
|
2074
|
+
onDragEvent: null,
|
|
2075
|
+
lineWrapping: false,
|
|
1548
2076
|
lineNumbers: false,
|
|
1549
2077
|
gutter: false,
|
|
2078
|
+
fixedGutter: false,
|
|
1550
2079
|
firstLineNumber: 1,
|
|
1551
2080
|
readOnly: false,
|
|
1552
|
-
|
|
2081
|
+
dragDrop: true,
|
|
1553
2082
|
onChange: null,
|
|
1554
2083
|
onCursorActivity: null,
|
|
1555
2084
|
onGutterClick: null,
|
|
1556
2085
|
onHighlightComplete: null,
|
|
2086
|
+
onUpdate: null,
|
|
1557
2087
|
onFocus: null, onBlur: null, onScroll: null,
|
|
1558
2088
|
matchBrackets: false,
|
|
1559
2089
|
workTime: 100,
|
|
1560
2090
|
workDelay: 200,
|
|
2091
|
+
pollInterval: 100,
|
|
1561
2092
|
undoDepth: 40,
|
|
1562
2093
|
tabindex: null,
|
|
1563
|
-
|
|
2094
|
+
autofocus: null,
|
|
2095
|
+
lineNumberFormatter: function(integer) { return integer; }
|
|
1564
2096
|
};
|
|
1565
2097
|
|
|
2098
|
+
var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
|
|
2099
|
+
var mac = ios || /Mac/.test(navigator.platform);
|
|
2100
|
+
var win = /Win/.test(navigator.platform);
|
|
2101
|
+
|
|
1566
2102
|
// Known modes, by name and by MIME
|
|
1567
|
-
var modes = {}, mimeModes = {};
|
|
2103
|
+
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
|
|
1568
2104
|
CodeMirror.defineMode = function(name, mode) {
|
|
1569
2105
|
if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
|
|
2106
|
+
if (arguments.length > 2) {
|
|
2107
|
+
mode.dependencies = [];
|
|
2108
|
+
for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
|
|
2109
|
+
}
|
|
1570
2110
|
modes[name] = mode;
|
|
1571
2111
|
};
|
|
1572
2112
|
CodeMirror.defineMIME = function(mime, spec) {
|
|
1573
2113
|
mimeModes[mime] = spec;
|
|
1574
2114
|
};
|
|
1575
|
-
CodeMirror.
|
|
2115
|
+
CodeMirror.resolveMode = function(spec) {
|
|
1576
2116
|
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
|
|
1577
2117
|
spec = mimeModes[spec];
|
|
1578
|
-
if (typeof spec == "string")
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
return mfactory(options,
|
|
2118
|
+
else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
|
|
2119
|
+
return CodeMirror.resolveMode("application/xml");
|
|
2120
|
+
if (typeof spec == "string") return {name: spec};
|
|
2121
|
+
else return spec || {name: "null"};
|
|
2122
|
+
};
|
|
2123
|
+
CodeMirror.getMode = function(options, spec) {
|
|
2124
|
+
var spec = CodeMirror.resolveMode(spec);
|
|
2125
|
+
var mfactory = modes[spec.name];
|
|
2126
|
+
if (!mfactory) return CodeMirror.getMode(options, "text/plain");
|
|
2127
|
+
return mfactory(options, spec);
|
|
1588
2128
|
};
|
|
1589
2129
|
CodeMirror.listModes = function() {
|
|
1590
2130
|
var list = [];
|
|
@@ -1595,20 +2135,141 @@ var CodeMirror = (function() {
|
|
|
1595
2135
|
CodeMirror.listMIMEs = function() {
|
|
1596
2136
|
var list = [];
|
|
1597
2137
|
for (var m in mimeModes)
|
|
1598
|
-
if (mimeModes.propertyIsEnumerable(m)) list.push(m);
|
|
2138
|
+
if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});
|
|
1599
2139
|
return list;
|
|
1600
2140
|
};
|
|
1601
2141
|
|
|
1602
|
-
var extensions = {};
|
|
2142
|
+
var extensions = CodeMirror.extensions = {};
|
|
1603
2143
|
CodeMirror.defineExtension = function(name, func) {
|
|
1604
2144
|
extensions[name] = func;
|
|
1605
2145
|
};
|
|
1606
2146
|
|
|
2147
|
+
var commands = CodeMirror.commands = {
|
|
2148
|
+
selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
|
|
2149
|
+
killLine: function(cm) {
|
|
2150
|
+
var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
|
|
2151
|
+
if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0});
|
|
2152
|
+
else cm.replaceRange("", from, sel ? to : {line: from.line});
|
|
2153
|
+
},
|
|
2154
|
+
deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});},
|
|
2155
|
+
undo: function(cm) {cm.undo();},
|
|
2156
|
+
redo: function(cm) {cm.redo();},
|
|
2157
|
+
goDocStart: function(cm) {cm.setCursor(0, 0, true);},
|
|
2158
|
+
goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},
|
|
2159
|
+
goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},
|
|
2160
|
+
goLineStartSmart: function(cm) {
|
|
2161
|
+
var cur = cm.getCursor();
|
|
2162
|
+
var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/));
|
|
2163
|
+
cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);
|
|
2164
|
+
},
|
|
2165
|
+
goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},
|
|
2166
|
+
goLineUp: function(cm) {cm.moveV(-1, "line");},
|
|
2167
|
+
goLineDown: function(cm) {cm.moveV(1, "line");},
|
|
2168
|
+
goPageUp: function(cm) {cm.moveV(-1, "page");},
|
|
2169
|
+
goPageDown: function(cm) {cm.moveV(1, "page");},
|
|
2170
|
+
goCharLeft: function(cm) {cm.moveH(-1, "char");},
|
|
2171
|
+
goCharRight: function(cm) {cm.moveH(1, "char");},
|
|
2172
|
+
goColumnLeft: function(cm) {cm.moveH(-1, "column");},
|
|
2173
|
+
goColumnRight: function(cm) {cm.moveH(1, "column");},
|
|
2174
|
+
goWordLeft: function(cm) {cm.moveH(-1, "word");},
|
|
2175
|
+
goWordRight: function(cm) {cm.moveH(1, "word");},
|
|
2176
|
+
delCharLeft: function(cm) {cm.deleteH(-1, "char");},
|
|
2177
|
+
delCharRight: function(cm) {cm.deleteH(1, "char");},
|
|
2178
|
+
delWordLeft: function(cm) {cm.deleteH(-1, "word");},
|
|
2179
|
+
delWordRight: function(cm) {cm.deleteH(1, "word");},
|
|
2180
|
+
indentAuto: function(cm) {cm.indentSelection("smart");},
|
|
2181
|
+
indentMore: function(cm) {cm.indentSelection("add");},
|
|
2182
|
+
indentLess: function(cm) {cm.indentSelection("subtract");},
|
|
2183
|
+
insertTab: function(cm) {cm.replaceSelection("\t", "end");},
|
|
2184
|
+
defaultTab: function(cm) {
|
|
2185
|
+
if (cm.somethingSelected()) cm.indentSelection("add");
|
|
2186
|
+
else cm.replaceSelection("\t", "end");
|
|
2187
|
+
},
|
|
2188
|
+
transposeChars: function(cm) {
|
|
2189
|
+
var cur = cm.getCursor(), line = cm.getLine(cur.line);
|
|
2190
|
+
if (cur.ch > 0 && cur.ch < line.length - 1)
|
|
2191
|
+
cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
|
|
2192
|
+
{line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
|
|
2193
|
+
},
|
|
2194
|
+
newlineAndIndent: function(cm) {
|
|
2195
|
+
cm.replaceSelection("\n", "end");
|
|
2196
|
+
cm.indentLine(cm.getCursor().line);
|
|
2197
|
+
},
|
|
2198
|
+
toggleOverwrite: function(cm) {cm.toggleOverwrite();}
|
|
2199
|
+
};
|
|
2200
|
+
|
|
2201
|
+
var keyMap = CodeMirror.keyMap = {};
|
|
2202
|
+
keyMap.basic = {
|
|
2203
|
+
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
|
|
2204
|
+
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
|
|
2205
|
+
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
|
|
2206
|
+
"Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
|
|
2207
|
+
};
|
|
2208
|
+
// Note that the save and find-related commands aren't defined by
|
|
2209
|
+
// default. Unknown commands are simply ignored.
|
|
2210
|
+
keyMap.pcDefault = {
|
|
2211
|
+
"Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
|
|
2212
|
+
"Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
|
|
2213
|
+
"Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
|
|
2214
|
+
"Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
|
|
2215
|
+
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
|
|
2216
|
+
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
|
|
2217
|
+
fallthrough: "basic"
|
|
2218
|
+
};
|
|
2219
|
+
keyMap.macDefault = {
|
|
2220
|
+
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
|
|
2221
|
+
"Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
|
|
2222
|
+
"Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
|
|
2223
|
+
"Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
|
|
2224
|
+
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
|
|
2225
|
+
"Cmd-[": "indentLess", "Cmd-]": "indentMore",
|
|
2226
|
+
fallthrough: ["basic", "emacsy"]
|
|
2227
|
+
};
|
|
2228
|
+
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
|
|
2229
|
+
keyMap.emacsy = {
|
|
2230
|
+
"Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
|
|
2231
|
+
"Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
|
|
2232
|
+
"Ctrl-V": "goPageUp", "Shift-Ctrl-V": "goPageDown", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft",
|
|
2233
|
+
"Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
|
|
2234
|
+
};
|
|
2235
|
+
|
|
2236
|
+
function getKeyMap(val) {
|
|
2237
|
+
if (typeof val == "string") return keyMap[val];
|
|
2238
|
+
else return val;
|
|
2239
|
+
}
|
|
2240
|
+
function lookupKey(name, extraMap, map, handle, stop) {
|
|
2241
|
+
function lookup(map) {
|
|
2242
|
+
map = getKeyMap(map);
|
|
2243
|
+
var found = map[name];
|
|
2244
|
+
if (found != null && handle(found)) return true;
|
|
2245
|
+
if (map.nofallthrough) {
|
|
2246
|
+
if (stop) stop();
|
|
2247
|
+
return true;
|
|
2248
|
+
}
|
|
2249
|
+
var fallthrough = map.fallthrough;
|
|
2250
|
+
if (fallthrough == null) return false;
|
|
2251
|
+
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
|
|
2252
|
+
return lookup(fallthrough);
|
|
2253
|
+
for (var i = 0, e = fallthrough.length; i < e; ++i) {
|
|
2254
|
+
if (lookup(fallthrough[i])) return true;
|
|
2255
|
+
}
|
|
2256
|
+
return false;
|
|
2257
|
+
}
|
|
2258
|
+
if (extraMap && lookup(extraMap)) return true;
|
|
2259
|
+
return lookup(map);
|
|
2260
|
+
}
|
|
2261
|
+
function isModifierKey(event) {
|
|
2262
|
+
var name = keyNames[e_prop(event, "keyCode")];
|
|
2263
|
+
return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
|
|
2264
|
+
}
|
|
2265
|
+
|
|
1607
2266
|
CodeMirror.fromTextArea = function(textarea, options) {
|
|
1608
2267
|
if (!options) options = {};
|
|
1609
2268
|
options.value = textarea.value;
|
|
1610
2269
|
if (!options.tabindex && textarea.tabindex)
|
|
1611
2270
|
options.tabindex = textarea.tabindex;
|
|
2271
|
+
if (options.autofocus == null && textarea.getAttribute("autofocus") != null)
|
|
2272
|
+
options.autofocus = true;
|
|
1612
2273
|
|
|
1613
2274
|
function save() {textarea.value = instance.getValue();}
|
|
1614
2275
|
if (textarea.form) {
|
|
@@ -1631,6 +2292,7 @@ var CodeMirror = (function() {
|
|
|
1631
2292
|
textarea.parentNode.insertBefore(node, textarea.nextSibling);
|
|
1632
2293
|
}, options);
|
|
1633
2294
|
instance.save = save;
|
|
2295
|
+
instance.getTextArea = function() { return textarea; };
|
|
1634
2296
|
instance.toTextArea = function() {
|
|
1635
2297
|
save();
|
|
1636
2298
|
textarea.parentNode.removeChild(instance.getWrapperElement());
|
|
@@ -1657,16 +2319,17 @@ var CodeMirror = (function() {
|
|
|
1657
2319
|
}
|
|
1658
2320
|
return nstate;
|
|
1659
2321
|
}
|
|
1660
|
-
CodeMirror.
|
|
2322
|
+
CodeMirror.copyState = copyState;
|
|
1661
2323
|
function startState(mode, a1, a2) {
|
|
1662
2324
|
return mode.startState ? mode.startState(a1, a2) : true;
|
|
1663
2325
|
}
|
|
1664
|
-
CodeMirror.
|
|
2326
|
+
CodeMirror.startState = startState;
|
|
1665
2327
|
|
|
1666
2328
|
// The character stream used by a mode's parser.
|
|
1667
|
-
function StringStream(string) {
|
|
2329
|
+
function StringStream(string, tabSize) {
|
|
1668
2330
|
this.pos = this.start = 0;
|
|
1669
2331
|
this.string = string;
|
|
2332
|
+
this.tabSize = tabSize || 8;
|
|
1670
2333
|
}
|
|
1671
2334
|
StringStream.prototype = {
|
|
1672
2335
|
eol: function() {return this.pos >= this.string.length;},
|
|
@@ -1698,8 +2361,8 @@ var CodeMirror = (function() {
|
|
|
1698
2361
|
if (found > -1) {this.pos = found; return true;}
|
|
1699
2362
|
},
|
|
1700
2363
|
backUp: function(n) {this.pos -= n;},
|
|
1701
|
-
column: function() {return countColumn(this.string, this.start);},
|
|
1702
|
-
indentation: function() {return countColumn(this.string);},
|
|
2364
|
+
column: function() {return countColumn(this.string, this.start, this.tabSize);},
|
|
2365
|
+
indentation: function() {return countColumn(this.string, null, this.tabSize);},
|
|
1703
2366
|
match: function(pattern, consume, caseInsensitive) {
|
|
1704
2367
|
if (typeof pattern == "string") {
|
|
1705
2368
|
function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
|
|
@@ -1707,8 +2370,7 @@ var CodeMirror = (function() {
|
|
|
1707
2370
|
if (consume !== false) this.pos += pattern.length;
|
|
1708
2371
|
return true;
|
|
1709
2372
|
}
|
|
1710
|
-
}
|
|
1711
|
-
else {
|
|
2373
|
+
} else {
|
|
1712
2374
|
var match = this.string.slice(this.pos).match(pattern);
|
|
1713
2375
|
if (match && consume !== false) this.pos += match[0].length;
|
|
1714
2376
|
return match;
|
|
@@ -1718,18 +2380,95 @@ var CodeMirror = (function() {
|
|
|
1718
2380
|
};
|
|
1719
2381
|
CodeMirror.StringStream = StringStream;
|
|
1720
2382
|
|
|
2383
|
+
function MarkedText(from, to, className, marker) {
|
|
2384
|
+
this.from = from; this.to = to; this.style = className; this.marker = marker;
|
|
2385
|
+
}
|
|
2386
|
+
MarkedText.prototype = {
|
|
2387
|
+
attach: function(line) { this.marker.set.push(line); },
|
|
2388
|
+
detach: function(line) {
|
|
2389
|
+
var ix = indexOf(this.marker.set, line);
|
|
2390
|
+
if (ix > -1) this.marker.set.splice(ix, 1);
|
|
2391
|
+
},
|
|
2392
|
+
split: function(pos, lenBefore) {
|
|
2393
|
+
if (this.to <= pos && this.to != null) return null;
|
|
2394
|
+
var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
|
|
2395
|
+
var to = this.to == null ? null : this.to - pos + lenBefore;
|
|
2396
|
+
return new MarkedText(from, to, this.style, this.marker);
|
|
2397
|
+
},
|
|
2398
|
+
dup: function() { return new MarkedText(null, null, this.style, this.marker); },
|
|
2399
|
+
clipTo: function(fromOpen, from, toOpen, to, diff) {
|
|
2400
|
+
if (fromOpen && to > this.from && (to < this.to || this.to == null))
|
|
2401
|
+
this.from = null;
|
|
2402
|
+
else if (this.from != null && this.from >= from)
|
|
2403
|
+
this.from = Math.max(to, this.from) + diff;
|
|
2404
|
+
if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
|
|
2405
|
+
this.to = null;
|
|
2406
|
+
else if (this.to != null && this.to > from)
|
|
2407
|
+
this.to = to < this.to ? this.to + diff : from;
|
|
2408
|
+
},
|
|
2409
|
+
isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
|
|
2410
|
+
sameSet: function(x) { return this.marker == x.marker; }
|
|
2411
|
+
};
|
|
2412
|
+
|
|
2413
|
+
function Bookmark(pos) {
|
|
2414
|
+
this.from = pos; this.to = pos; this.line = null;
|
|
2415
|
+
}
|
|
2416
|
+
Bookmark.prototype = {
|
|
2417
|
+
attach: function(line) { this.line = line; },
|
|
2418
|
+
detach: function(line) { if (this.line == line) this.line = null; },
|
|
2419
|
+
split: function(pos, lenBefore) {
|
|
2420
|
+
if (pos < this.from) {
|
|
2421
|
+
this.from = this.to = (this.from - pos) + lenBefore;
|
|
2422
|
+
return this;
|
|
2423
|
+
}
|
|
2424
|
+
},
|
|
2425
|
+
isDead: function() { return this.from > this.to; },
|
|
2426
|
+
clipTo: function(fromOpen, from, toOpen, to, diff) {
|
|
2427
|
+
if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {
|
|
2428
|
+
this.from = 0; this.to = -1;
|
|
2429
|
+
} else if (this.from > from) {
|
|
2430
|
+
this.from = this.to = Math.max(to, this.from) + diff;
|
|
2431
|
+
}
|
|
2432
|
+
},
|
|
2433
|
+
sameSet: function(x) { return false; },
|
|
2434
|
+
find: function() {
|
|
2435
|
+
if (!this.line || !this.line.parent) return null;
|
|
2436
|
+
return {line: lineNo(this.line), ch: this.from};
|
|
2437
|
+
},
|
|
2438
|
+
clear: function() {
|
|
2439
|
+
if (this.line) {
|
|
2440
|
+
var found = indexOf(this.line.marked, this);
|
|
2441
|
+
if (found != -1) this.line.marked.splice(found, 1);
|
|
2442
|
+
this.line = null;
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
};
|
|
2446
|
+
|
|
1721
2447
|
// Line objects. These hold state related to a line, including
|
|
1722
2448
|
// highlighting info (the styles array).
|
|
1723
2449
|
function Line(text, styles) {
|
|
1724
2450
|
this.styles = styles || [text, null];
|
|
1725
|
-
this.stateAfter = null;
|
|
1726
2451
|
this.text = text;
|
|
1727
|
-
this.
|
|
2452
|
+
this.height = 1;
|
|
2453
|
+
this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
|
|
2454
|
+
this.stateAfter = this.parent = this.hidden = null;
|
|
2455
|
+
}
|
|
2456
|
+
Line.inheritMarks = function(text, orig) {
|
|
2457
|
+
var ln = new Line(text), mk = orig && orig.marked;
|
|
2458
|
+
if (mk) {
|
|
2459
|
+
for (var i = 0; i < mk.length; ++i) {
|
|
2460
|
+
if (mk[i].to == null && mk[i].style) {
|
|
2461
|
+
var newmk = ln.marked || (ln.marked = []), mark = mk[i];
|
|
2462
|
+
var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
return ln;
|
|
1728
2467
|
}
|
|
1729
2468
|
Line.prototype = {
|
|
1730
2469
|
// Replace a piece of a line, keeping the styles around it intact.
|
|
1731
|
-
replace: function(from,
|
|
1732
|
-
var st = [], mk = this.marked;
|
|
2470
|
+
replace: function(from, to_, text) {
|
|
2471
|
+
var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;
|
|
1733
2472
|
copyStyles(0, from, this.styles, st);
|
|
1734
2473
|
if (text) st.push(text, null);
|
|
1735
2474
|
copyStyles(to, this.text.length, this.styles, st);
|
|
@@ -1737,40 +2476,102 @@ var CodeMirror = (function() {
|
|
|
1737
2476
|
this.text = this.text.slice(0, from) + text + this.text.slice(to);
|
|
1738
2477
|
this.stateAfter = null;
|
|
1739
2478
|
if (mk) {
|
|
1740
|
-
var diff = text.length - (to - from)
|
|
1741
|
-
function fix(n) {return n <= Math.min(to, to + diff) ? n : n + diff;}
|
|
2479
|
+
var diff = text.length - (to - from);
|
|
1742
2480
|
for (var i = 0; i < mk.length; ++i) {
|
|
1743
|
-
var mark = mk[i]
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
if (del || mark.from >= mark.to) {mk.splice(i, 1); i--;}
|
|
2481
|
+
var mark = mk[i];
|
|
2482
|
+
mark.clipTo(from == null, from || 0, to_ == null, to, diff);
|
|
2483
|
+
if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}
|
|
1747
2484
|
}
|
|
1748
2485
|
}
|
|
1749
2486
|
},
|
|
1750
|
-
// Split a
|
|
2487
|
+
// Split a part off a line, keeping styles and markers intact.
|
|
1751
2488
|
split: function(pos, textBefore) {
|
|
1752
|
-
var st = [textBefore, null];
|
|
2489
|
+
var st = [textBefore, null], mk = this.marked;
|
|
1753
2490
|
copyStyles(pos, this.text.length, this.styles, st);
|
|
1754
|
-
|
|
2491
|
+
var taken = new Line(textBefore + this.text.slice(pos), st);
|
|
2492
|
+
if (mk) {
|
|
2493
|
+
for (var i = 0; i < mk.length; ++i) {
|
|
2494
|
+
var mark = mk[i];
|
|
2495
|
+
var newmark = mark.split(pos, textBefore.length);
|
|
2496
|
+
if (newmark) {
|
|
2497
|
+
if (!taken.marked) taken.marked = [];
|
|
2498
|
+
taken.marked.push(newmark); newmark.attach(taken);
|
|
2499
|
+
if (newmark == mark) mk.splice(i--, 1);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
return taken;
|
|
1755
2504
|
},
|
|
1756
|
-
|
|
1757
|
-
var
|
|
1758
|
-
|
|
1759
|
-
this.
|
|
1760
|
-
|
|
1761
|
-
|
|
2505
|
+
append: function(line) {
|
|
2506
|
+
var mylen = this.text.length, mk = line.marked, mymk = this.marked;
|
|
2507
|
+
this.text += line.text;
|
|
2508
|
+
copyStyles(0, line.text.length, line.styles, this.styles);
|
|
2509
|
+
if (mymk) {
|
|
2510
|
+
for (var i = 0; i < mymk.length; ++i)
|
|
2511
|
+
if (mymk[i].to == null) mymk[i].to = mylen;
|
|
2512
|
+
}
|
|
2513
|
+
if (mk && mk.length) {
|
|
2514
|
+
if (!mymk) this.marked = mymk = [];
|
|
2515
|
+
outer: for (var i = 0; i < mk.length; ++i) {
|
|
2516
|
+
var mark = mk[i];
|
|
2517
|
+
if (!mark.from) {
|
|
2518
|
+
for (var j = 0; j < mymk.length; ++j) {
|
|
2519
|
+
var mymark = mymk[j];
|
|
2520
|
+
if (mymark.to == mylen && mymark.sameSet(mark)) {
|
|
2521
|
+
mymark.to = mark.to == null ? null : mark.to + mylen;
|
|
2522
|
+
if (mymark.isDead()) {
|
|
2523
|
+
mymark.detach(this);
|
|
2524
|
+
mk.splice(i--, 1);
|
|
2525
|
+
}
|
|
2526
|
+
continue outer;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
mymk.push(mark);
|
|
2531
|
+
mark.attach(this);
|
|
2532
|
+
mark.from += mylen;
|
|
2533
|
+
if (mark.to != null) mark.to += mylen;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
1762
2536
|
},
|
|
1763
|
-
|
|
2537
|
+
fixMarkEnds: function(other) {
|
|
2538
|
+
var mk = this.marked, omk = other.marked;
|
|
2539
|
+
if (!mk) return;
|
|
2540
|
+
outer: for (var i = 0; i < mk.length; ++i) {
|
|
2541
|
+
var mark = mk[i], close = mark.to == null;
|
|
2542
|
+
if (close && omk) {
|
|
2543
|
+
for (var j = 0; j < omk.length; ++j) {
|
|
2544
|
+
var om = omk[j];
|
|
2545
|
+
if (!om.sameSet(mark) || om.from != null) continue
|
|
2546
|
+
if (mark.from == this.text.length && om.to == 0) {
|
|
2547
|
+
omk.splice(j, 1);
|
|
2548
|
+
mk.splice(i--, 1);
|
|
2549
|
+
continue outer;
|
|
2550
|
+
} else {
|
|
2551
|
+
close = false; break;
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
if (close) mark.to = this.text.length;
|
|
2556
|
+
}
|
|
2557
|
+
},
|
|
2558
|
+
fixMarkStarts: function() {
|
|
1764
2559
|
var mk = this.marked;
|
|
1765
2560
|
if (!mk) return;
|
|
1766
2561
|
for (var i = 0; i < mk.length; ++i)
|
|
1767
|
-
if (mk[i] ==
|
|
2562
|
+
if (mk[i].from == null) mk[i].from = 0;
|
|
2563
|
+
},
|
|
2564
|
+
addMark: function(mark) {
|
|
2565
|
+
mark.attach(this);
|
|
2566
|
+
if (this.marked == null) this.marked = [];
|
|
2567
|
+
this.marked.push(mark);
|
|
2568
|
+
this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});
|
|
1768
2569
|
},
|
|
1769
2570
|
// Run the given mode's parser over a line, update the styles
|
|
1770
2571
|
// array, which contains alternating fragments of text and CSS
|
|
1771
2572
|
// classes.
|
|
1772
|
-
highlight: function(mode, state) {
|
|
1773
|
-
var stream = new StringStream(this.text), st = this.styles, pos = 0;
|
|
2573
|
+
highlight: function(mode, state, tabSize) {
|
|
2574
|
+
var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0;
|
|
1774
2575
|
var changed = false, curWord = st[0], prevWord;
|
|
1775
2576
|
if (this.text == "" && mode.blankLine) mode.blankLine(state);
|
|
1776
2577
|
while (!stream.eol()) {
|
|
@@ -1811,74 +2612,131 @@ var CodeMirror = (function() {
|
|
|
1811
2612
|
className: style || null,
|
|
1812
2613
|
state: state};
|
|
1813
2614
|
},
|
|
1814
|
-
indentation: function() {return countColumn(this.text);},
|
|
2615
|
+
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
|
|
1815
2616
|
// Produces an HTML fragment for the line, taking selection,
|
|
1816
2617
|
// marking, and highlighting into account.
|
|
1817
|
-
getHTML: function(
|
|
1818
|
-
var html = [];
|
|
1819
|
-
|
|
1820
|
-
html.push(this.className ? '<pre class="' + this.className + '">': "<pre>");
|
|
1821
|
-
function span(text, style) {
|
|
2618
|
+
getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {
|
|
2619
|
+
var html = [], first = true, col = 0;
|
|
2620
|
+
function span_(text, style) {
|
|
1822
2621
|
if (!text) return;
|
|
1823
|
-
|
|
1824
|
-
|
|
2622
|
+
// Work around a bug where, in some compat modes, IE ignores leading spaces
|
|
2623
|
+
if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
|
|
2624
|
+
first = false;
|
|
2625
|
+
if (text.indexOf("\t") == -1) {
|
|
2626
|
+
col += text.length;
|
|
2627
|
+
var escaped = htmlEscape(text);
|
|
2628
|
+
} else {
|
|
2629
|
+
var escaped = "";
|
|
2630
|
+
for (var pos = 0;;) {
|
|
2631
|
+
var idx = text.indexOf("\t", pos);
|
|
2632
|
+
if (idx == -1) {
|
|
2633
|
+
escaped += htmlEscape(text.slice(pos));
|
|
2634
|
+
col += text.length - pos;
|
|
2635
|
+
break;
|
|
2636
|
+
} else {
|
|
2637
|
+
col += idx - pos;
|
|
2638
|
+
var tab = makeTab(col);
|
|
2639
|
+
escaped += htmlEscape(text.slice(pos, idx)) + tab.html;
|
|
2640
|
+
col += tab.width;
|
|
2641
|
+
pos = idx + 1;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
if (style) html.push('<span class="', style, '">', escaped, "</span>");
|
|
2646
|
+
else html.push(escaped);
|
|
2647
|
+
}
|
|
2648
|
+
var span = span_;
|
|
2649
|
+
if (wrapAt != null) {
|
|
2650
|
+
var outPos = 0, open = "<span id=\"" + wrapId + "\">";
|
|
2651
|
+
span = function(text, style) {
|
|
2652
|
+
var l = text.length;
|
|
2653
|
+
if (wrapAt >= outPos && wrapAt < outPos + l) {
|
|
2654
|
+
if (wrapAt > outPos) {
|
|
2655
|
+
span_(text.slice(0, wrapAt - outPos), style);
|
|
2656
|
+
// See comment at the definition of spanAffectsWrapping
|
|
2657
|
+
if (wrapWBR) html.push("<wbr>");
|
|
2658
|
+
}
|
|
2659
|
+
html.push(open);
|
|
2660
|
+
var cut = wrapAt - outPos;
|
|
2661
|
+
span_(opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
|
|
2662
|
+
html.push("</span>");
|
|
2663
|
+
if (opera) span_(text.slice(cut + 1), style);
|
|
2664
|
+
wrapAt--;
|
|
2665
|
+
outPos += l;
|
|
2666
|
+
} else {
|
|
2667
|
+
outPos += l;
|
|
2668
|
+
span_(text, style);
|
|
2669
|
+
// Output empty wrapper when at end of line
|
|
2670
|
+
// (Gecko and IE8+ do strange wrapping when adding a space
|
|
2671
|
+
// to the end of the line. Other browsers don't react well
|
|
2672
|
+
// to zero-width spaces. So we do hideous browser sniffing
|
|
2673
|
+
// to determine which to use.)
|
|
2674
|
+
if (outPos == wrapAt && outPos == len)
|
|
2675
|
+
html.push(open + (gecko || (ie && !ie_lt8) ? "​" : " ") + "</span>");
|
|
2676
|
+
// Stop outputting HTML when gone sufficiently far beyond measure
|
|
2677
|
+
else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
1825
2680
|
}
|
|
2681
|
+
|
|
1826
2682
|
var st = this.styles, allText = this.text, marked = this.marked;
|
|
1827
|
-
if (sfrom == sto) sfrom = null;
|
|
1828
2683
|
var len = allText.length;
|
|
1829
|
-
|
|
2684
|
+
function styleToClass(style) {
|
|
2685
|
+
if (!style) return null;
|
|
2686
|
+
return "cm-" + style.replace(/ +/g, " cm-");
|
|
2687
|
+
}
|
|
1830
2688
|
|
|
1831
|
-
if (!allText &&
|
|
1832
|
-
span(" "
|
|
1833
|
-
else if (!marked
|
|
2689
|
+
if (!allText && wrapAt == null) {
|
|
2690
|
+
span(" ");
|
|
2691
|
+
} else if (!marked || !marked.length) {
|
|
1834
2692
|
for (var i = 0, ch = 0; ch < len; i+=2) {
|
|
1835
|
-
var str = st[i], l = str.length;
|
|
2693
|
+
var str = st[i], style = st[i+1], l = str.length;
|
|
1836
2694
|
if (ch + l > len) str = str.slice(0, len - ch);
|
|
1837
2695
|
ch += l;
|
|
1838
|
-
span(str,
|
|
2696
|
+
span(str, styleToClass(style));
|
|
1839
2697
|
}
|
|
1840
|
-
else {
|
|
2698
|
+
} else {
|
|
1841
2699
|
var pos = 0, i = 0, text = "", style, sg = 0;
|
|
1842
|
-
var
|
|
1843
|
-
function
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
2700
|
+
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
|
|
2701
|
+
function advanceMarks() {
|
|
2702
|
+
var m;
|
|
2703
|
+
while (markpos < marked.length &&
|
|
2704
|
+
((m = marked[markpos]).from == pos || m.from == null)) {
|
|
2705
|
+
if (m.style != null) marks.push(m);
|
|
2706
|
+
++markpos;
|
|
2707
|
+
}
|
|
2708
|
+
nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
|
|
2709
|
+
for (var i = 0; i < marks.length; ++i) {
|
|
2710
|
+
var to = marks[i].to;
|
|
2711
|
+
if (to == null) to = Infinity;
|
|
2712
|
+
if (to == pos) marks.splice(i--, 1);
|
|
2713
|
+
else nextChange = Math.min(to, nextChange);
|
|
1847
2714
|
}
|
|
1848
2715
|
}
|
|
1849
|
-
|
|
2716
|
+
var m = 0;
|
|
1850
2717
|
while (pos < len) {
|
|
1851
|
-
|
|
1852
|
-
var
|
|
1853
|
-
|
|
1854
|
-
if (
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
if (mark.from > pos) upto = Math.min(upto, mark.from);
|
|
1863
|
-
else {
|
|
1864
|
-
extraStyle += " " + mark.style;
|
|
1865
|
-
if (mark.to != null) upto = Math.min(upto, mark.to);
|
|
2718
|
+
if (nextChange == pos) advanceMarks();
|
|
2719
|
+
var upto = Math.min(len, nextChange);
|
|
2720
|
+
while (true) {
|
|
2721
|
+
if (text) {
|
|
2722
|
+
var end = pos + text.length;
|
|
2723
|
+
var appliedStyle = style;
|
|
2724
|
+
for (var j = 0; j < marks.length; ++j)
|
|
2725
|
+
appliedStyle = (appliedStyle ? appliedStyle + " " : "") + marks[j].style;
|
|
2726
|
+
span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
|
2727
|
+
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
|
2728
|
+
pos = end;
|
|
1866
2729
|
}
|
|
1867
|
-
|
|
1868
|
-
for (;;) {
|
|
1869
|
-
var end = pos + text.length;
|
|
1870
|
-
var appliedStyle = style;
|
|
1871
|
-
if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
|
|
1872
|
-
span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
|
1873
|
-
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
|
1874
|
-
pos = end;
|
|
1875
|
-
text = st[i++]; style = "cm-" + st[i++];
|
|
2730
|
+
text = st[i++]; style = styleToClass(st[i++]);
|
|
1876
2731
|
}
|
|
1877
2732
|
}
|
|
1878
|
-
if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
|
|
1879
2733
|
}
|
|
1880
|
-
if (includePre) html.push("</pre>");
|
|
1881
2734
|
return html.join("");
|
|
2735
|
+
},
|
|
2736
|
+
cleanUp: function() {
|
|
2737
|
+
this.parent = null;
|
|
2738
|
+
if (this.marked)
|
|
2739
|
+
for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);
|
|
1882
2740
|
}
|
|
1883
2741
|
};
|
|
1884
2742
|
// Utility used by replace and split above
|
|
@@ -1888,8 +2746,7 @@ var CodeMirror = (function() {
|
|
|
1888
2746
|
if (state == 0) {
|
|
1889
2747
|
if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
|
|
1890
2748
|
if (end >= from) state = 1;
|
|
1891
|
-
}
|
|
1892
|
-
else if (state == 1) {
|
|
2749
|
+
} else if (state == 1) {
|
|
1893
2750
|
if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
|
|
1894
2751
|
else dest.push(part, source[i+1]);
|
|
1895
2752
|
}
|
|
@@ -1897,36 +2754,229 @@ var CodeMirror = (function() {
|
|
|
1897
2754
|
}
|
|
1898
2755
|
}
|
|
1899
2756
|
|
|
2757
|
+
// Data structure that holds the sequence of lines.
|
|
2758
|
+
function LeafChunk(lines) {
|
|
2759
|
+
this.lines = lines;
|
|
2760
|
+
this.parent = null;
|
|
2761
|
+
for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
|
|
2762
|
+
lines[i].parent = this;
|
|
2763
|
+
height += lines[i].height;
|
|
2764
|
+
}
|
|
2765
|
+
this.height = height;
|
|
2766
|
+
}
|
|
2767
|
+
LeafChunk.prototype = {
|
|
2768
|
+
chunkSize: function() { return this.lines.length; },
|
|
2769
|
+
remove: function(at, n, callbacks) {
|
|
2770
|
+
for (var i = at, e = at + n; i < e; ++i) {
|
|
2771
|
+
var line = this.lines[i];
|
|
2772
|
+
this.height -= line.height;
|
|
2773
|
+
line.cleanUp();
|
|
2774
|
+
if (line.handlers)
|
|
2775
|
+
for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);
|
|
2776
|
+
}
|
|
2777
|
+
this.lines.splice(at, n);
|
|
2778
|
+
},
|
|
2779
|
+
collapse: function(lines) {
|
|
2780
|
+
lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
|
|
2781
|
+
},
|
|
2782
|
+
insertHeight: function(at, lines, height) {
|
|
2783
|
+
this.height += height;
|
|
2784
|
+
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
|
|
2785
|
+
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
|
|
2786
|
+
},
|
|
2787
|
+
iterN: function(at, n, op) {
|
|
2788
|
+
for (var e = at + n; at < e; ++at)
|
|
2789
|
+
if (op(this.lines[at])) return true;
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
function BranchChunk(children) {
|
|
2793
|
+
this.children = children;
|
|
2794
|
+
var size = 0, height = 0;
|
|
2795
|
+
for (var i = 0, e = children.length; i < e; ++i) {
|
|
2796
|
+
var ch = children[i];
|
|
2797
|
+
size += ch.chunkSize(); height += ch.height;
|
|
2798
|
+
ch.parent = this;
|
|
2799
|
+
}
|
|
2800
|
+
this.size = size;
|
|
2801
|
+
this.height = height;
|
|
2802
|
+
this.parent = null;
|
|
2803
|
+
}
|
|
2804
|
+
BranchChunk.prototype = {
|
|
2805
|
+
chunkSize: function() { return this.size; },
|
|
2806
|
+
remove: function(at, n, callbacks) {
|
|
2807
|
+
this.size -= n;
|
|
2808
|
+
for (var i = 0; i < this.children.length; ++i) {
|
|
2809
|
+
var child = this.children[i], sz = child.chunkSize();
|
|
2810
|
+
if (at < sz) {
|
|
2811
|
+
var rm = Math.min(n, sz - at), oldHeight = child.height;
|
|
2812
|
+
child.remove(at, rm, callbacks);
|
|
2813
|
+
this.height -= oldHeight - child.height;
|
|
2814
|
+
if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
|
|
2815
|
+
if ((n -= rm) == 0) break;
|
|
2816
|
+
at = 0;
|
|
2817
|
+
} else at -= sz;
|
|
2818
|
+
}
|
|
2819
|
+
if (this.size - n < 25) {
|
|
2820
|
+
var lines = [];
|
|
2821
|
+
this.collapse(lines);
|
|
2822
|
+
this.children = [new LeafChunk(lines)];
|
|
2823
|
+
this.children[0].parent = this;
|
|
2824
|
+
}
|
|
2825
|
+
},
|
|
2826
|
+
collapse: function(lines) {
|
|
2827
|
+
for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
|
|
2828
|
+
},
|
|
2829
|
+
insert: function(at, lines) {
|
|
2830
|
+
var height = 0;
|
|
2831
|
+
for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
|
|
2832
|
+
this.insertHeight(at, lines, height);
|
|
2833
|
+
},
|
|
2834
|
+
insertHeight: function(at, lines, height) {
|
|
2835
|
+
this.size += lines.length;
|
|
2836
|
+
this.height += height;
|
|
2837
|
+
for (var i = 0, e = this.children.length; i < e; ++i) {
|
|
2838
|
+
var child = this.children[i], sz = child.chunkSize();
|
|
2839
|
+
if (at <= sz) {
|
|
2840
|
+
child.insertHeight(at, lines, height);
|
|
2841
|
+
if (child.lines && child.lines.length > 50) {
|
|
2842
|
+
while (child.lines.length > 50) {
|
|
2843
|
+
var spilled = child.lines.splice(child.lines.length - 25, 25);
|
|
2844
|
+
var newleaf = new LeafChunk(spilled);
|
|
2845
|
+
child.height -= newleaf.height;
|
|
2846
|
+
this.children.splice(i + 1, 0, newleaf);
|
|
2847
|
+
newleaf.parent = this;
|
|
2848
|
+
}
|
|
2849
|
+
this.maybeSpill();
|
|
2850
|
+
}
|
|
2851
|
+
break;
|
|
2852
|
+
}
|
|
2853
|
+
at -= sz;
|
|
2854
|
+
}
|
|
2855
|
+
},
|
|
2856
|
+
maybeSpill: function() {
|
|
2857
|
+
if (this.children.length <= 10) return;
|
|
2858
|
+
var me = this;
|
|
2859
|
+
do {
|
|
2860
|
+
var spilled = me.children.splice(me.children.length - 5, 5);
|
|
2861
|
+
var sibling = new BranchChunk(spilled);
|
|
2862
|
+
if (!me.parent) { // Become the parent node
|
|
2863
|
+
var copy = new BranchChunk(me.children);
|
|
2864
|
+
copy.parent = me;
|
|
2865
|
+
me.children = [copy, sibling];
|
|
2866
|
+
me = copy;
|
|
2867
|
+
} else {
|
|
2868
|
+
me.size -= sibling.size;
|
|
2869
|
+
me.height -= sibling.height;
|
|
2870
|
+
var myIndex = indexOf(me.parent.children, me);
|
|
2871
|
+
me.parent.children.splice(myIndex + 1, 0, sibling);
|
|
2872
|
+
}
|
|
2873
|
+
sibling.parent = me.parent;
|
|
2874
|
+
} while (me.children.length > 10);
|
|
2875
|
+
me.parent.maybeSpill();
|
|
2876
|
+
},
|
|
2877
|
+
iter: function(from, to, op) { this.iterN(from, to - from, op); },
|
|
2878
|
+
iterN: function(at, n, op) {
|
|
2879
|
+
for (var i = 0, e = this.children.length; i < e; ++i) {
|
|
2880
|
+
var child = this.children[i], sz = child.chunkSize();
|
|
2881
|
+
if (at < sz) {
|
|
2882
|
+
var used = Math.min(n, sz - at);
|
|
2883
|
+
if (child.iterN(at, used, op)) return true;
|
|
2884
|
+
if ((n -= used) == 0) break;
|
|
2885
|
+
at = 0;
|
|
2886
|
+
} else at -= sz;
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
};
|
|
2890
|
+
|
|
2891
|
+
function getLineAt(chunk, n) {
|
|
2892
|
+
while (!chunk.lines) {
|
|
2893
|
+
for (var i = 0;; ++i) {
|
|
2894
|
+
var child = chunk.children[i], sz = child.chunkSize();
|
|
2895
|
+
if (n < sz) { chunk = child; break; }
|
|
2896
|
+
n -= sz;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
return chunk.lines[n];
|
|
2900
|
+
}
|
|
2901
|
+
function lineNo(line) {
|
|
2902
|
+
if (line.parent == null) return null;
|
|
2903
|
+
var cur = line.parent, no = indexOf(cur.lines, line);
|
|
2904
|
+
for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
|
|
2905
|
+
for (var i = 0, e = chunk.children.length; ; ++i) {
|
|
2906
|
+
if (chunk.children[i] == cur) break;
|
|
2907
|
+
no += chunk.children[i].chunkSize();
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
return no;
|
|
2911
|
+
}
|
|
2912
|
+
function lineAtHeight(chunk, h) {
|
|
2913
|
+
var n = 0;
|
|
2914
|
+
outer: do {
|
|
2915
|
+
for (var i = 0, e = chunk.children.length; i < e; ++i) {
|
|
2916
|
+
var child = chunk.children[i], ch = child.height;
|
|
2917
|
+
if (h < ch) { chunk = child; continue outer; }
|
|
2918
|
+
h -= ch;
|
|
2919
|
+
n += child.chunkSize();
|
|
2920
|
+
}
|
|
2921
|
+
return n;
|
|
2922
|
+
} while (!chunk.lines);
|
|
2923
|
+
for (var i = 0, e = chunk.lines.length; i < e; ++i) {
|
|
2924
|
+
var line = chunk.lines[i], lh = line.height;
|
|
2925
|
+
if (h < lh) break;
|
|
2926
|
+
h -= lh;
|
|
2927
|
+
}
|
|
2928
|
+
return n + i;
|
|
2929
|
+
}
|
|
2930
|
+
function heightAtLine(chunk, n) {
|
|
2931
|
+
var h = 0;
|
|
2932
|
+
outer: do {
|
|
2933
|
+
for (var i = 0, e = chunk.children.length; i < e; ++i) {
|
|
2934
|
+
var child = chunk.children[i], sz = child.chunkSize();
|
|
2935
|
+
if (n < sz) { chunk = child; continue outer; }
|
|
2936
|
+
n -= sz;
|
|
2937
|
+
h += child.height;
|
|
2938
|
+
}
|
|
2939
|
+
return h;
|
|
2940
|
+
} while (!chunk.lines);
|
|
2941
|
+
for (var i = 0; i < n; ++i) h += chunk.lines[i].height;
|
|
2942
|
+
return h;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
1900
2945
|
// The history object 'chunks' changes that are made close together
|
|
1901
2946
|
// and at almost the same time into bigger undoable units.
|
|
1902
2947
|
function History() {
|
|
1903
2948
|
this.time = 0;
|
|
1904
2949
|
this.done = []; this.undone = [];
|
|
2950
|
+
this.compound = 0;
|
|
2951
|
+
this.closed = false;
|
|
1905
2952
|
}
|
|
1906
2953
|
History.prototype = {
|
|
1907
2954
|
addChange: function(start, added, old) {
|
|
1908
2955
|
this.undone.length = 0;
|
|
1909
|
-
var time = +new Date,
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
for (var i = last.added - oldoff, e = old.length; i < e; ++i)
|
|
1926
|
-
last.old.push(old[i]);
|
|
1927
|
-
if (last.added < added) last.added = added;
|
|
2956
|
+
var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
|
|
2957
|
+
var dtime = time - this.time;
|
|
2958
|
+
|
|
2959
|
+
if (this.compound && cur && !this.closed) {
|
|
2960
|
+
cur.push({start: start, added: added, old: old});
|
|
2961
|
+
} else if (dtime > 400 || !last || this.closed ||
|
|
2962
|
+
last.start > start + old.length || last.start + last.added < start) {
|
|
2963
|
+
this.done.push([{start: start, added: added, old: old}]);
|
|
2964
|
+
this.closed = false;
|
|
2965
|
+
} else {
|
|
2966
|
+
var startBefore = Math.max(0, last.start - start),
|
|
2967
|
+
endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
|
|
2968
|
+
for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
|
|
2969
|
+
for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
|
|
2970
|
+
if (startBefore) last.start = start;
|
|
2971
|
+
last.added += added - (old.length - startBefore - endAfter);
|
|
1928
2972
|
}
|
|
1929
2973
|
this.time = time;
|
|
2974
|
+
},
|
|
2975
|
+
startCompound: function() {
|
|
2976
|
+
if (!this.compound++) this.closed = true;
|
|
2977
|
+
},
|
|
2978
|
+
endCompound: function() {
|
|
2979
|
+
if (!--this.compound) this.closed = true;
|
|
1930
2980
|
}
|
|
1931
2981
|
};
|
|
1932
2982
|
|
|
@@ -1946,59 +2996,92 @@ var CodeMirror = (function() {
|
|
|
1946
2996
|
else e.cancelBubble = true;
|
|
1947
2997
|
}
|
|
1948
2998
|
function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
|
|
2999
|
+
CodeMirror.e_stop = e_stop;
|
|
3000
|
+
CodeMirror.e_preventDefault = e_preventDefault;
|
|
3001
|
+
CodeMirror.e_stopPropagation = e_stopPropagation;
|
|
3002
|
+
|
|
1949
3003
|
function e_target(e) {return e.target || e.srcElement;}
|
|
1950
3004
|
function e_button(e) {
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
3005
|
+
var b = e.which;
|
|
3006
|
+
if (b == null) {
|
|
3007
|
+
if (e.button & 1) b = 1;
|
|
3008
|
+
else if (e.button & 2) b = 3;
|
|
3009
|
+
else if (e.button & 4) b = 2;
|
|
3010
|
+
}
|
|
3011
|
+
if (mac && e.ctrlKey && b == 1) b = 3;
|
|
3012
|
+
return b;
|
|
3013
|
+
}
|
|
3014
|
+
|
|
3015
|
+
// Allow 3rd-party code to override event properties by adding an override
|
|
3016
|
+
// object to an event object.
|
|
3017
|
+
function e_prop(e, prop) {
|
|
3018
|
+
var overridden = e.override && e.override.hasOwnProperty(prop);
|
|
3019
|
+
return overridden ? e.override[prop] : e[prop];
|
|
1955
3020
|
}
|
|
1956
3021
|
|
|
1957
3022
|
// Event handler registration. If disconnect is true, it'll return a
|
|
1958
3023
|
// function that unregisters the handler.
|
|
1959
3024
|
function connect(node, type, handler, disconnect) {
|
|
1960
|
-
function wrapHandler(event) {handler(event || window.event);}
|
|
1961
3025
|
if (typeof node.addEventListener == "function") {
|
|
1962
|
-
node.addEventListener(type,
|
|
1963
|
-
if (disconnect) return function() {node.removeEventListener(type,
|
|
1964
|
-
}
|
|
1965
|
-
|
|
3026
|
+
node.addEventListener(type, handler, false);
|
|
3027
|
+
if (disconnect) return function() {node.removeEventListener(type, handler, false);};
|
|
3028
|
+
} else {
|
|
3029
|
+
var wrapHandler = function(event) {handler(event || window.event);};
|
|
1966
3030
|
node.attachEvent("on" + type, wrapHandler);
|
|
1967
3031
|
if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
|
|
1968
3032
|
}
|
|
1969
3033
|
}
|
|
3034
|
+
CodeMirror.connect = connect;
|
|
1970
3035
|
|
|
1971
3036
|
function Delayed() {this.id = null;}
|
|
1972
3037
|
Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
|
|
1973
3038
|
|
|
1974
|
-
|
|
1975
|
-
// innerHTML of a PRE tag.
|
|
1976
|
-
var badInnerHTML = (function() {
|
|
1977
|
-
var pre = document.createElement("pre");
|
|
1978
|
-
pre.innerHTML = " "; return !pre.innerHTML;
|
|
1979
|
-
})();
|
|
3039
|
+
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
|
|
1980
3040
|
|
|
1981
3041
|
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
|
|
1982
3042
|
var ie = /MSIE \d/.test(navigator.userAgent);
|
|
3043
|
+
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
|
|
3044
|
+
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
|
|
3045
|
+
var quirksMode = ie && document.documentMode == 5;
|
|
3046
|
+
var webkit = /WebKit\//.test(navigator.userAgent);
|
|
3047
|
+
var chrome = /Chrome\//.test(navigator.userAgent);
|
|
3048
|
+
var opera = /Opera\//.test(navigator.userAgent);
|
|
1983
3049
|
var safari = /Apple Computer/.test(navigator.vendor);
|
|
3050
|
+
var khtml = /KHTML\//.test(navigator.userAgent);
|
|
3051
|
+
var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
|
|
3052
|
+
|
|
3053
|
+
// Detect drag-and-drop
|
|
3054
|
+
var dragAndDrop = function() {
|
|
3055
|
+
// There is *some* kind of drag-and-drop support in IE6-8, but I
|
|
3056
|
+
// couldn't get it to work yet.
|
|
3057
|
+
if (ie_lt9) return false;
|
|
3058
|
+
var div = document.createElement('div');
|
|
3059
|
+
return "draggable" in div || "dragDrop" in div;
|
|
3060
|
+
}();
|
|
1984
3061
|
|
|
1985
|
-
var lineSep = "\n";
|
|
1986
3062
|
// Feature-detect whether newlines in textareas are converted to \r\n
|
|
1987
|
-
|
|
3063
|
+
var lineSep = function () {
|
|
1988
3064
|
var te = document.createElement("textarea");
|
|
1989
3065
|
te.value = "foo\nbar";
|
|
1990
|
-
if (te.value.indexOf("\r") > -1)
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
3066
|
+
if (te.value.indexOf("\r") > -1) return "\r\n";
|
|
3067
|
+
return "\n";
|
|
3068
|
+
}();
|
|
3069
|
+
|
|
3070
|
+
// For a reason I have yet to figure out, some browsers disallow
|
|
3071
|
+
// word wrapping between certain characters *only* if a new inline
|
|
3072
|
+
// element is started between them. This makes it hard to reliably
|
|
3073
|
+
// measure the position of things, since that requires inserting an
|
|
3074
|
+
// extra span. This terribly fragile set of regexps matches the
|
|
3075
|
+
// character combinations that suffer from this phenomenon on the
|
|
3076
|
+
// various browsers.
|
|
3077
|
+
var spanAffectsWrapping = /^$/; // Won't match any two-character string
|
|
3078
|
+
if (gecko) spanAffectsWrapping = /$'/;
|
|
3079
|
+
else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
|
|
3080
|
+
else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
|
|
1998
3081
|
|
|
1999
3082
|
// Counts the column offset in a string, taking tabs into account.
|
|
2000
3083
|
// Used mostly to find indentation.
|
|
2001
|
-
function countColumn(string, end) {
|
|
3084
|
+
function countColumn(string, end, tabSize) {
|
|
2002
3085
|
if (end == null) {
|
|
2003
3086
|
end = string.search(/[^\s\u00a0]/);
|
|
2004
3087
|
if (end == -1) end = string.length;
|
|
@@ -2014,42 +3097,67 @@ var CodeMirror = (function() {
|
|
|
2014
3097
|
if (elt.currentStyle) return elt.currentStyle;
|
|
2015
3098
|
return window.getComputedStyle(elt, null);
|
|
2016
3099
|
}
|
|
2017
|
-
|
|
2018
|
-
// If screen==true, it returns screen (rather than page) coordinates.
|
|
3100
|
+
|
|
2019
3101
|
function eltOffset(node, screen) {
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
3102
|
+
// Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
|
|
3103
|
+
// since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
|
|
3104
|
+
try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
|
|
3105
|
+
catch(e) { box = {top: 0, left: 0}; }
|
|
3106
|
+
if (!screen) {
|
|
3107
|
+
// Get the toplevel scroll, working around browser differences.
|
|
3108
|
+
if (window.pageYOffset == null) {
|
|
3109
|
+
var t = document.documentElement || document.body.parentNode;
|
|
3110
|
+
if (t.scrollTop == null) t = document.body;
|
|
3111
|
+
box.top += t.scrollTop; box.left += t.scrollLeft;
|
|
3112
|
+
} else {
|
|
3113
|
+
box.top += window.pageYOffset; box.left += window.pageXOffset;
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
return box;
|
|
2031
3117
|
}
|
|
3118
|
+
|
|
2032
3119
|
// Get a node's text content.
|
|
2033
3120
|
function eltText(node) {
|
|
2034
3121
|
return node.textContent || node.innerText || node.nodeValue || "";
|
|
2035
3122
|
}
|
|
3123
|
+
function selectInput(node) {
|
|
3124
|
+
if (ios) { // Mobile Safari apparently has a bug where select() is broken.
|
|
3125
|
+
node.selectionStart = 0;
|
|
3126
|
+
node.selectionEnd = node.value.length;
|
|
3127
|
+
} else node.select();
|
|
3128
|
+
}
|
|
2036
3129
|
|
|
2037
3130
|
// Operations on {line, ch} objects.
|
|
2038
3131
|
function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
|
|
2039
3132
|
function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
|
|
2040
3133
|
function copyPos(x) {return {line: x.line, ch: x.ch};}
|
|
2041
3134
|
|
|
2042
|
-
var escapeElement = document.createElement("
|
|
3135
|
+
var escapeElement = document.createElement("pre");
|
|
2043
3136
|
function htmlEscape(str) {
|
|
2044
|
-
escapeElement.
|
|
3137
|
+
escapeElement.textContent = str;
|
|
2045
3138
|
return escapeElement.innerHTML;
|
|
2046
3139
|
}
|
|
3140
|
+
// Recent (late 2011) Opera betas insert bogus newlines at the start
|
|
3141
|
+
// of the textContent, so we strip those.
|
|
3142
|
+
if (htmlEscape("a") == "\na") {
|
|
3143
|
+
htmlEscape = function(str) {
|
|
3144
|
+
escapeElement.textContent = str;
|
|
3145
|
+
return escapeElement.innerHTML.slice(1);
|
|
3146
|
+
};
|
|
3147
|
+
// Some IEs don't preserve tabs through innerHTML
|
|
3148
|
+
} else if (htmlEscape("\t") != "\t") {
|
|
3149
|
+
htmlEscape = function(str) {
|
|
3150
|
+
escapeElement.innerHTML = "";
|
|
3151
|
+
escapeElement.appendChild(document.createTextNode(str));
|
|
3152
|
+
return escapeElement.innerHTML;
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
2047
3155
|
CodeMirror.htmlEscape = htmlEscape;
|
|
2048
3156
|
|
|
2049
3157
|
// Used to position the cursor after an undo/redo by finding the
|
|
2050
3158
|
// last edited character.
|
|
2051
3159
|
function editEnd(from, to) {
|
|
2052
|
-
if (!to) return
|
|
3160
|
+
if (!to) return 0;
|
|
2053
3161
|
if (!from) return to.length;
|
|
2054
3162
|
for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
|
|
2055
3163
|
if (from.charAt(i) != to.charAt(j)) break;
|
|
@@ -2062,96 +3170,62 @@ var CodeMirror = (function() {
|
|
|
2062
3170
|
if (collection[i] == elt) return i;
|
|
2063
3171
|
return -1;
|
|
2064
3172
|
}
|
|
3173
|
+
function isWordChar(ch) {
|
|
3174
|
+
return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();
|
|
3175
|
+
}
|
|
2065
3176
|
|
|
2066
3177
|
// See if "".split is the broken IE version, if so, provide an
|
|
2067
3178
|
// alternative way to split lines.
|
|
2068
|
-
var splitLines
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
var
|
|
2072
|
-
|
|
2073
|
-
|
|
3179
|
+
var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
|
|
3180
|
+
var pos = 0, result = [], l = string.length;
|
|
3181
|
+
while (pos <= l) {
|
|
3182
|
+
var nl = string.indexOf("\n", pos);
|
|
3183
|
+
if (nl == -1) nl = string.length;
|
|
3184
|
+
var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
|
|
3185
|
+
var rt = line.indexOf("\r");
|
|
3186
|
+
if (rt != -1) {
|
|
3187
|
+
result.push(line.slice(0, rt));
|
|
3188
|
+
pos += rt + 1;
|
|
3189
|
+
} else {
|
|
3190
|
+
result.push(line);
|
|
2074
3191
|
pos = nl + 1;
|
|
2075
3192
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
else
|
|
2080
|
-
splitLines = function(string){return string.split(/\r?\n/);};
|
|
3193
|
+
}
|
|
3194
|
+
return result;
|
|
3195
|
+
} : function(string){return string.split(/\r\n?|\n/);};
|
|
2081
3196
|
CodeMirror.splitLines = splitLines;
|
|
2082
3197
|
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
}
|
|
2089
|
-
if (
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
// the anchor is put at the end, and the selection expanded to
|
|
2093
|
-
// the left. If you press shift-right, the anchor ends up at the
|
|
2094
|
-
// front. This is not what CodeMirror wants, so it does a
|
|
2095
|
-
// spurious modify() call to get out of limbo.
|
|
2096
|
-
setSelRange = function(te, start, end) {
|
|
2097
|
-
if (start == end)
|
|
2098
|
-
te.setSelectionRange(start, end);
|
|
2099
|
-
else {
|
|
2100
|
-
te.setSelectionRange(start, end - 1);
|
|
2101
|
-
window.getSelection().modify("extend", "forward", "character");
|
|
2102
|
-
}
|
|
2103
|
-
};
|
|
2104
|
-
else
|
|
2105
|
-
setSelRange = function(te, start, end) {
|
|
2106
|
-
try {te.setSelectionRange(start, end);}
|
|
2107
|
-
catch(e) {} // Fails on Firefox when textarea isn't part of the document
|
|
2108
|
-
};
|
|
2109
|
-
}
|
|
2110
|
-
// IE model. Don't ask.
|
|
2111
|
-
else {
|
|
2112
|
-
selRange = function(te) {
|
|
2113
|
-
try {var range = te.ownerDocument.selection.createRange();}
|
|
2114
|
-
catch(e) {return null;}
|
|
2115
|
-
if (!range || range.parentElement() != te) return null;
|
|
2116
|
-
var val = te.value, len = val.length, localRange = te.createTextRange();
|
|
2117
|
-
localRange.moveToBookmark(range.getBookmark());
|
|
2118
|
-
var endRange = te.createTextRange();
|
|
2119
|
-
endRange.collapse(false);
|
|
2120
|
-
|
|
2121
|
-
if (localRange.compareEndPoints("StartToEnd", endRange) > -1)
|
|
2122
|
-
return {start: len, end: len};
|
|
2123
|
-
|
|
2124
|
-
var start = -localRange.moveStart("character", -len);
|
|
2125
|
-
for (var i = val.indexOf("\r"); i > -1 && i < start; i = val.indexOf("\r", i+1), start++) {}
|
|
2126
|
-
|
|
2127
|
-
if (localRange.compareEndPoints("EndToEnd", endRange) > -1)
|
|
2128
|
-
return {start: start, end: len};
|
|
2129
|
-
|
|
2130
|
-
var end = -localRange.moveEnd("character", -len);
|
|
2131
|
-
for (var i = val.indexOf("\r"); i > -1 && i < end; i = val.indexOf("\r", i+1), end++) {}
|
|
2132
|
-
return {start: start, end: end};
|
|
2133
|
-
};
|
|
2134
|
-
setSelRange = function(te, start, end) {
|
|
2135
|
-
var range = te.createTextRange();
|
|
2136
|
-
range.collapse(true);
|
|
2137
|
-
var endrange = range.duplicate();
|
|
2138
|
-
var newlines = 0, txt = te.value;
|
|
2139
|
-
for (var pos = txt.indexOf("\n"); pos > -1 && pos < start; pos = txt.indexOf("\n", pos + 1))
|
|
2140
|
-
++newlines;
|
|
2141
|
-
range.move("character", start - newlines);
|
|
2142
|
-
for (; pos > -1 && pos < end; pos = txt.indexOf("\n", pos + 1))
|
|
2143
|
-
++newlines;
|
|
2144
|
-
endrange.move("character", end - newlines);
|
|
2145
|
-
range.setEndPoint("EndToEnd", endrange);
|
|
2146
|
-
range.select();
|
|
2147
|
-
};
|
|
2148
|
-
}
|
|
3198
|
+
var hasSelection = window.getSelection ? function(te) {
|
|
3199
|
+
try { return te.selectionStart != te.selectionEnd; }
|
|
3200
|
+
catch(e) { return false; }
|
|
3201
|
+
} : function(te) {
|
|
3202
|
+
try {var range = te.ownerDocument.selection.createRange();}
|
|
3203
|
+
catch(e) {}
|
|
3204
|
+
if (!range || range.parentElement() != te) return false;
|
|
3205
|
+
return range.compareEndPoints("StartToEnd", range) != 0;
|
|
3206
|
+
};
|
|
2149
3207
|
|
|
2150
3208
|
CodeMirror.defineMode("null", function() {
|
|
2151
3209
|
return {token: function(stream) {stream.skipToEnd();}};
|
|
2152
3210
|
});
|
|
2153
3211
|
CodeMirror.defineMIME("text/plain", "null");
|
|
2154
3212
|
|
|
3213
|
+
var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
|
|
3214
|
+
19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
|
|
3215
|
+
36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
|
|
3216
|
+
46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
|
|
3217
|
+
186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
|
|
3218
|
+
221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
|
|
3219
|
+
63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
|
|
3220
|
+
CodeMirror.keyNames = keyNames;
|
|
3221
|
+
(function() {
|
|
3222
|
+
// Number keys
|
|
3223
|
+
for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
|
|
3224
|
+
// Alphabetic keys
|
|
3225
|
+
for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
|
|
3226
|
+
// Function keys
|
|
3227
|
+
for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
|
|
3228
|
+
})();
|
|
3229
|
+
|
|
2155
3230
|
return CodeMirror;
|
|
2156
|
-
})()
|
|
2157
|
-
;
|
|
3231
|
+
})();
|